2010-04-19 152 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']