【问题标题】:Filter with arbitrary number or Q objects combined by OR logical operator使用 OR 逻辑运算符组合的任意数量或 Q 对象进行过滤
【发布时间】:2017-02-11 05:57:14
【问题描述】:

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/

语法是filter(**kwargs)

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

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

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

你能帮帮我吗?

【问题讨论】:

    标签: django django-orm


    【解决方案1】:
    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))
    

    【讨论】:

      【解决方案2】:

      你可以这样做:

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

      【讨论】:

      • 亲爱的 Todor,感谢您的回答。看起来很有希望。我必须消化。如果可行,我很乐意接受。
      • 很好的答案!对我来说,颠倒 Q 对象的顺序看起来更直观。不幸的是,这不起作用,因为第二个参数必须支持迭代。
      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 2014-04-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-20
        • 1970-01-01
        相关资源
        最近更新 更多