2012-01-20 59 views
11

我有一個django模型和一個字段代表一個用戶的全名。我的客戶希望我設置一個篩選器,以基於一組字符串搜索用戶,其中全部名稱都必須是不區分大小寫的。過濾Django數據庫的字段包含數組中的任何值

例如

如果用戶full_name = "Keith, Thomson S."

而且我有一個列表['keith','s','thomson']

我想執行的過濾器相當於

Profile.objects.filter(full_name__icontains='keith',full_name__icontains='s',full_name__icontains='thomson') 

問題是這樣的名單可以動態大小 - 所以我不知道如何做到這一點。

任何人有任何想法?

回答

33

請連續調用filter,像這樣:

queryset = Profile.objects.all() 
strings = ['keith', 's', 'thompson'] 
for string in strings: 
    queryset = queryset.filter(full_name__icontains=string) 

另外,您可以&一起一堆Q對象:

condition = Q(full_name__icontains=s[0]) 
for string in strings[1:]: 
    condition &= Q(full_name__icontains=string) 
queryset = Profile.objects.filter(condition) 

寫這個,避免了顯式循環的更隱蔽的方式:

import operator 
# ... 
condition = reduce(operator.and_, [Q(full_name__icontains=s) for s in strings]) 
queryset = Profile.objects.filter(condition) 
+0

我不知道鏈接所有這些過濾器後,最終的sql表達式會變成什麼樣子。 – akonsu

+0

@akonsu我只是試了一下(好吧,類似的東西) - 它被轉換爲'where子句中的一系列'AND's,即'full_name LIKE%keith%AND full_name LIKE%s%AND ... ' –

+2

@isbadawi,+1 - 請注意,多個Q對象的默認運算符是AND,因此您可以在不使用reduce/operator.and_的情況下運行「* [Q1,Q2,Q3]」。 –

2

somethi ng沿着這些線:


array = ['keith', 's', 'thomson'] 
regex = '^.*(%s).*$' % '|'.join(array) 
Profile.objects.filter(full_name__iregex=regex) 

編輯:這是錯誤的,OP想要名稱,其中包含所有字符串同時。

3

使用operator功能and_or_Q()條件

匹配所有的字符串( and_

Profile.objects.filter(reduce(and_, [Q(full_name__icontains=q) for q in li])) 

from operator import and_, or_ 
li = ['keith', 's', 'thompson'] 

項目匹配任何字符串,該清單結合更短(or_

Profile.objects.filter(reduce(or_, [Q(full_name__icontains=q) for q in li])) 

Q()函數實現__or__()__and__()連接兩個Q()對象組合在一起,這樣他們就可以使用相應的operator函數調用。

相關問題