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