大文字と小文字を区別せずに一致させたい名前のリストがありますが、以下のようなループを使用せずにそれを行う方法はありますか?
a = ['name1', 'name2', 'name3']
result = any([Name.objects.filter(name__iexact=name) for name in a])
残念ながら、no___iin
_フィールドルックアップがあります。しかし、次のように役立つ可能性のある iregex
があります。
_result = Name.objects.filter(name__iregex=r'(name1|name2|name3)')
_
あるいは:
_a = ['name1', 'name2', 'name3']
result = Name.objects.filter(name__iregex=r'(' + '|'.join(a) + ')')
_
正規表現で特別な文字を含むことができる場合は、それらを適切に escape する必要があることに注意してください。
ニュース:Djano 1.7では、独自のルックアップを作成できるため、適切に初期化した後、実際にfilter(name__iin=['name1', 'name2', 'name3'])
を使用できます。詳細については、 https://docs.djangoproject.com/en/1.7/ref/models/lookups/ を参照してください。
Postgresqlでは、次のように大文字と小文字を区別しないインデックスを作成してみてください。
https://stackoverflow.com/a/4124225/110274
次に、クエリを実行します。
from Django.db.models import Q
name_filter = Q()
for name in names:
name_filter |= Q(name__iexact=name)
result = Name.objects.filter(name_filter)
インデックス検索は、正規表現マッチングクエリよりも高速に実行されます。
Djangoクエリ関数 とアノテーションを使用してこれを行う別の方法
from Django.db.models.functions import Lower
Record.objects.annotate(name_lower=Lower('name')).filter(name_lower__in=['two', 'one']
少なくともMySQLでは、実際に大文字と小文字を区別するために、テーブルにutf8_bin
照合順序を設定する必要があることに注意してください。それ以外の場合、大文字と小文字は区別されますが、大文字と小文字は区別されません。例えば。
>>> models.Person.objects.filter(first__in=['John', 'Ringo'])
[<Person: John Lennon>, <Person: Ringo Starr>]
>>> models.Person.objects.filter(first__in=['joHn', 'RiNgO'])
[<Person: John Lennon>, <Person: Ringo Starr>]
したがって、移植性が重要ではなく、MySQLを使用している場合は、問題を完全に無視することを選択できます。
Rasmujが言ったことに加えて、そのようなユーザー入力をエスケープします
import re
result = Name.objects.filter(name__iregex=r'(' + '|'.join([re.escape(n) for n in a]) + ')')
Exgenyのアイデアを2つのライナーに拡張しています。
import functools
Name.objects.filter(functools.reduce(lambda acc,x: acc | Q(name_iexact=x)), names, Q()))
これは、ユーザーをフィルタリングするためのカスタムユーザーモデルclassmethod
の例ですメールで大文字と小文字を区別しない
from Django.db.models import Q
@classmethod
def get_users_by_email_query(cls, emails):
q = Q()
for email in [email.strip() for email in emails]:
q = q | Q(email__iexact=email)
return cls.objects.filter(q)