8

Djangoのほぼすべての種類のルックアップには、大文字と小文字を区別しないバージョンがあります。

ケースが正しくないと確信している場合にルックアップを実行する必要があるため、これは問題です。

Products.objects.filter(code__in=[user_entered_data_as_list])

これに対処するために私にできることはありますか?人々はこの問題を回避するためのハックを思いついたことがありますか?

4

7 に答える 7

9

MySQLデータベース自体で大文字と小文字を区別しないようにすることで、これを回避しました。Djangoの人々がこれを機能として追加したり、独自のフィールドルックアップを提供する方法に関するドキュメントを提供したりすることに興味があるとは思えません(各dbバックエンドにコードを提供しなくても可能であると仮定します)

これを行う1つの方法は、確かに不格好です。

products = Product.objects.filter(**normal_filters_here)
results = Product.objects.none()
for d in user_entered_data_as_list:
    results |= products.filter(code__iexact=d)
于 2010-10-12T17:36:41.743 に答える
2

データベースがMySQLの場合、DjangoはINクエリを大文字と小文字を区別せずに扱います。他人のことはよくわかりませんが

編集1:

model_name.objects.filter(location__city__name__in': ['Tokio','Paris',])

都市名が次のような結果になります

トキオまたはトキオまたはトキオまたはパリまたはパリまたはパリ

于 2016-05-20T11:00:43.727 に答える
1

競合が発生しない場合、考えられる回避策は、オブジェクトが保存されているときとであるときの両方で、文字列を大文字または小文字に変換することfilterです。

于 2010-03-02T04:00:29.237 に答える
1

これは、ケースで準備されたDB値を必要としないソリューションです。また、DBエンジン側でフィルタリングを行うため、を繰り返すよりもはるかに高いパフォーマンスが得られobjects.all()ます。

def case_insensitive_in_filter(fieldname, iterable):
    """returns Q(fieldname__in=iterable) but case insensitive"""
    q_list = map(lambda n: Q(**{fieldname+'__iexact': n}), iterable)
    return reduce(lambda a, b: a | b, q_list)

他の効率的な解決策は、非常に移植性の高いraw-SQLlower()関数でextraを使用することです。

MyModel.objects.extra(
    select={'lower_' + fieldname: 'lower(' + fieldname + ')'}
).filter('lover_' + fieldname + '__in'=[x.lower() for x in iterable])
于 2013-12-30T03:53:42.147 に答える
1

もう1つの解決策は、大雑把ではありますが、元の文字列のさまざまなケースを「in」フィルターのリスト引数に含めることです。例:['a'、'b'、'c']の代わりに、代わりに['a'、'b'、'c'、'A'、'B'、'C']を使用します。

文字列のリストからそのようなリストを作成する関数は次のとおりです。

def build_list_for_case_insensitive_query(the_strings):
    results = list()
    for the_string in the_strings:
        results.append(the_string)
        if the_string.upper() not in results:
            results.append(the_string.upper())
        if the_string.lower() not in results:
            results.append(the_string.lower())
    return results
于 2015-11-14T22:17:00.993 に答える
1

Qオブジェクトを使用したルックアップは、データベースを1回だけヒットするように構築できます。

from django.db.models import Q

user_inputed_codes = ['eN', 'De', 'FR']

lookup = Q()
for code in user_inputed_codes:
    lookup |= Q(code__iexact=code)
filtered_products = Products.objects.filter(lookup)
于 2019-07-21T13:02:50.657 に答える
0

少しエレガントな方法はこれです:

[x for x in Products.objects.all() if x.code.upper() in [y.upper() for y in user_entered_data_as_list]]
于 2012-09-22T12:29:36.427 に答える