我们可以展开列表,并用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(..) 的工作方式类似于 函数式编程 中已知的“折叠”(这是 catamorphism 的一个特例)。
因此,我们将在两者之间添加or_s,从而得到Q(name__contains='xx') | Q(name__contains='yy')。这是一个基本上对过滤条件进行编码的对象:这意味着name 列应该__contains 子字符串'xx',或子字符串'yy'。
注意:如果你想匹配大小写敏感(所以行带有XX,或Xx,或xX,或xx是所有个候选),然后将__contains替换为__<b>i</b>contains。
编辑:根据您的评论,如果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))
)
所以只有在phrases_filter 元素上包含至少的情况下,我们才会执行过滤。