用 OR 逻辑运算符组合任意数字或 Q objects 的过滤器

Filter with arbitrary number or Q objects combined by OR logical operator

Django 1.10.1

搜索表单。用户插入由空格分隔的单词。 需要在标题字段中找到 objects 和 ANY 这些词。

我打算使用这样的东西:

Article.objects.filter(
    Q(title__icontains="table") | Q(title__icontains="helm")
)

我可以轻松地制作Q objects:q = Q(title__icontains="table").

但障碍是如何将参数传递给过滤器方法。

https://docs.djangoproject.com/en/1.10/topics/db/queries/

语法是filter(**kwargs).

通过循环我可以准备这样的字典:

q_objects = {"1": Q(title__icontains="table"), "2": Q(title__icontains="glasses")}

但问题在于 "|"
如何将它传递给过滤方法对我来说是个谜。换句话说,我无法使用 OR 逻辑运算符构建过滤器。

你能帮帮我吗?

你可以这样做:

queryset = MyModel.objects.all()
queries = ['table, helm']
filter_ = 'title__icontains'

queryset.filter(reduce(lambda q1,q2: q1|q2, [Q(**{filter_: q}) for q in queries], Q()))

#This will build a QuerySet similar to this one:
queryset.filter(Q(title__icontains='table')|Q(title__icontains='helm')) 
query = Q()
for word in words:
    query |= Q(title__icontains=word)
Article.objects.filter(query)

from operator import __or__ as OR
from functools import reduce

query = [Q(title__icontains=word) for word in words]
Article.objects.filter(reduce(OR, query))

与@Todor 提出并基于this post 的同一行,我更喜欢这种语法:

reduce(operator.or_, (Q(title__icontains=x) for x in ['x', 'y', 'z']))

您的示例的完整代码可以是:

list_of_words = ['table', 'helm']   # words wanted by the user

Article.objects.filter(
     reduce(operator.or_, (Q(title__icontains=word) for word in list_of_words))
)