2010-04-19 151 views
23

我有我想匹配大小写不敏感的名称列表,有没有办法做到这一点,而不使用如下循环?Django查询不区分大小写的列表匹配

a = ['name1', 'name2', 'name3'] 
result = any([Name.objects.filter(name__iexact=name) for name in a]) 

回答

27

抱歉,系统有没有__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/

+2

Postgres的支持不区分大小写的索引,所以该情况下,可以更快地对比iregex匹配每个项目上运行单独的“iexact”查询。在django的postgres后端,“iexact”搜索使用UPPER()转换,因此在该行的UPPER()上使用自定义索引时,可以获得加速。 – Evgeny 2012-09-24 01:56:17

+5

我希望他们能实施__iin – JREAM 2013-06-19 20:02:41

+0

@Evgeny我希望你能添加一个答案,或给我们一个链接。谢谢! – 2014-01-29 09:32:00

3

添加到什么Rasmuj说,逃避任何用户输入像这样

import re 
result = Name.objects.filter(name__iregex=r'(' + '|'.join([re.escape(n) for n in a]) + ')') 
3

记住,至少在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,则可以选择完全忽略该问题。

15

在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) 

索引搜索会跑的比正则表达式匹配的查询速度更快。

+0

谢谢!有想法。 – 2014-01-31 08:26:40

+1

小心这个代码!如果变量名称为空,那么.filter将返回该模型的所有对象! – Benjamin 2016-08-15 16:28:32

1

另一种方式此使用django query functions和注释

from django.db.models.functions import Lower 
Record.objects.annotate(name_lower=Lower('name')).filter(name_lower__in=['two', 'one']