使用OR逻辑运算符组合的任意数字或Q对象进行过滤

时间:2016-10-03 10:04:49

标签: django django-orm

Django 1.10.1

搜索表单。用户插入由空格分隔的单词。 必须在标题字段中找到具有 ANY 这些单词的对象。

我打算用这样的东西:

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

我可以轻松制作Q对象:q = Q(title__icontains =“table”)。

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

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

语法为过滤器(** kwargs)

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

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

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

你能帮帮我吗?

3 个答案:

答案 0 :(得分:2)

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))

答案 1 :(得分:1)

您可以这样做:

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')) 

答案 2 :(得分:1)

在@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))
)