Django 查询不区分大小写的数据
Django Query with Case Insensitive Data Both Ways
有很多类似的问题,但我只找到了部分解决方案。
我有一组用户存储为对象,具有名称属性 (User.name)。我希望使用用户输入 (Foo) 进行查询,这样我就可以(不区分大小写)找到所有用户:
- foo 在 User.name
- User.name 在 foo
例如,我希望用户能够输入 "Jeff William II" 和 return "Anderson Jeff William II"、"jeff william iii" 以及 "Jeff Will"和 "william ii"
我知道我可以使用 Q function 组合两个查询,我可以使用 annotate() 像这样转换 User.name (如果您发现此代码中的错误,我欢迎您进行编辑) :
users = User.objects.annotate(name_upper=Upper(name)).filter(Q(name_upper__icontains=foo) | Q(name_upper__in=foo))
但是我 运行 在使用 __in
匹配字符串中的多个字母时遇到了麻烦。因此,如果 User.name 是 "F",我在输入 Jeff 时会被击中,但如果 User.name 是 "JE",那么它不会显示。如何匹配多个字母,或者是否有更好的方法来进行此查询?
旁注:我最初使用以下方法解决了这个问题,但如果可能的话我更愿意进行查询。
for u in User.objects.all():
if u.name in foo or foo in u.name:
请不要使用Upper
。一个常见的误解是,通过将两个项目转换为大写(或小写),您进行了不区分大小写的相等性检查。某些字符,如 ß 没有 uppercase/lowercase,并且有更复杂的规则(整理)来考虑这些等价物。在 Python 中,人们使用 .casefold(…)
[python-doc]。
对于数据库,你可以简单地使用注释,然后使用两个检查:
from django.db.models import CharField, F, Q, Value
foo = 'Jeff William II'
User.objects.annotate(<b>foo=Value(foo, CharField())</b>).filter(
Q(name__icontains=<b>foo</b>) | Q(<b>foo__icontains=F('name')</b>)
)
有很多类似的问题,但我只找到了部分解决方案。 我有一组用户存储为对象,具有名称属性 (User.name)。我希望使用用户输入 (Foo) 进行查询,这样我就可以(不区分大小写)找到所有用户:
- foo 在 User.name
- User.name 在 foo
例如,我希望用户能够输入 "Jeff William II" 和 return "Anderson Jeff William II"、"jeff william iii" 以及 "Jeff Will"和 "william ii"
我知道我可以使用 Q function 组合两个查询,我可以使用 annotate() 像这样转换 User.name (如果您发现此代码中的错误,我欢迎您进行编辑) :
users = User.objects.annotate(name_upper=Upper(name)).filter(Q(name_upper__icontains=foo) | Q(name_upper__in=foo))
但是我 运行 在使用 __in
匹配字符串中的多个字母时遇到了麻烦。因此,如果 User.name 是 "F",我在输入 Jeff 时会被击中,但如果 User.name 是 "JE",那么它不会显示。如何匹配多个字母,或者是否有更好的方法来进行此查询?
旁注:我最初使用以下方法解决了这个问题,但如果可能的话我更愿意进行查询。
for u in User.objects.all():
if u.name in foo or foo in u.name:
请不要使用Upper
。一个常见的误解是,通过将两个项目转换为大写(或小写),您进行了不区分大小写的相等性检查。某些字符,如 ß 没有 uppercase/lowercase,并且有更复杂的规则(整理)来考虑这些等价物。在 Python 中,人们使用 .casefold(…)
[python-doc]。
对于数据库,你可以简单地使用注释,然后使用两个检查:
from django.db.models import CharField, F, Q, Value
foo = 'Jeff William II'
User.objects.annotate(<b>foo=Value(foo, CharField())</b>).filter(
Q(name__icontains=<b>foo</b>) | Q(<b>foo__icontains=F('name')</b>)
)