我有一个字符串列表:
phrases_filter = json.loads(request.GET['phrases_filter'])
['xx', 'yy']
我需要查找db中包含xx
OR yy
我试过这样:
Phrase.objects.filter(name__in phrases_filter)
但这只给了我名字xx
AND yy
答案 0 :(得分:2)
我们可以展开列表,并使用or-logic定义一组__contains
谓词:
from django.db.models import Q
from functools import reduce
from operator import or_
Phrase.objects.filter(
reduce(or_, (Q(name__contains=e) for e in phrases_filter))
)
在给定phrases_filter
的情况下,我们将生成相当于:
Phrase.objects.filter(
Q(name__contains='xx') | Q(name__contains='yy')
)
所以reduce(..)
将对Q(..)
个对象的生成器进行操作,此处为[Q(name__contains='xx'), Q(name__contains='yy')]
。 reduce(..)
的工作方式类似于函数式编程中所知的" fold " (这是 catamorphism 的一个特例)。
我们将在其间添加or_
,结果为Q(name__contains='xx') | Q(name__contains='yy')
。这是一个基本上编码过滤条件的对象:它表示name
列应该__contains
子串'xx'
或子串'yy'
。
注意:如果您想匹配敏感的案例(所以行包含
XX
,Xx
或{{1} },或xX
所有候选人),然后将xx
替换为__contains
。
编辑:根据您的评论,如果__icontains
为空,您希望所有行都匹配,我们可以使用phrases_filter
语句执行此操作:
if
因此,只有from django.db.models import Q
from functools import reduce
from operator import or_
queryset = Phrase.objects.all()
if phrases_filter:
queryset = filter(
reduce(or_, (Q(name__contains=e) for e in phrases_filter))
)
在元素上包含至少,我们才会执行过滤。