2012-01-20 13 views
11

私はdjangoモデルとユーザーフルネームを表すフィールドを持っています。私のクライアントは、文字列の配列に基づいてユーザーを検索するフィルターを設定し、そのすべてが大文字と小文字を区別しないようにする必要があります。私がリストを持っているfull_name = "Keith, Thomson S."フィルタ配列内の任意の値を含むフィールドのDjangoデータベース

、ユーザーが['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'句、' full_name LIKE%keith%AND full_name LIKE%s%AND AND ... ' –

+2

@isbadawi、+1 - 複数のQオブジェクトのデフォルト演算子はANDであるので、reduce */operator.and_を使わずに' * [Q1、Q2、Q3] 'だけでよいことに注意してください。 –

2

somethi


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

EDIT:これは間違っています。OPは、すべての文字列を同時に含む名前が必要です。 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'] 

アイテムのリストを組み合わせることoperator機能and_or_を使用して

3

でさえ短いです(or_

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

Q()関数は、2つのQ()オブジェクトに参加する__or__()__and__()を実装するので、それらは、対応するoperator機能を使用して呼び出すことができます。

関連する問題