【问题标题】:A Django ORM query using a mix of filter() and Q objects使用 filter() 和 Q 对象混合的 Django ORM 查询
【发布时间】:2010-11-13 01:23:05
【问题描述】:

我正在寻找使用原始 SQL 相当容易编写的稍微复杂的查询。这是原始查询的示例:

SELECT my,fields FROM sales WHERE is_paid = False OR status = 'toship' AND otherfield = 'FOO' AND anotherfield = 'BAR'

这很简单,它生成 is_paid = False 的所有结果,然后为我的 AND 匹配生成第二个结果集。

现在我了解了 Q 对象,我了解了过滤,但我似乎不知道如何在 Django ORM 中干净利落地实现这一点。

有什么建议吗?

谢谢

【问题讨论】:

    标签: django orm django-q


    【解决方案1】:

    您可以继续以某种动态的方式构建您的 Q 对象。

    例子:

    query1 = Q(is_paid=False)
    
    query2 = Q()
    
    if status:
        query2 = Q(status=status)
    
    if otherfield:
        query2 = query2 & Q(otherfield=otherfield)
    
    if anotherfield:
        query2 = query2 & Q(anotherfield=anotherfield)
    
    query = query1 | query2
    
    result = model.objects.filter(query)
    

    【讨论】:

      【解决方案2】:

      虽然 googletorp 是正确的,您不能使用字符串动态构造查询,但您可以使用字典参数来做到这一点。比如:

      model.objects.filter(Q(**mydict1) | Q(**mydict2))
      

      mydict1 和 2 的格式为:

      {'field1': 'value1'}
      {'field2__icontains': 'value2'}
      

      等等

      【讨论】:

        【解决方案3】:

        这样的事情应该可以工作:

        model.objects.filter(Q(is_paid=False) | Q(status='toship', otherfield='FOO', anotherfield='BAR'))
        

        编辑: 您不能像构造包含要在完成时执行的 SQL 语句的字符串那样动态地创建查询。如果你想这样做,我建议使用 if 状态、函数或最适合你的用例:

        if query == 'simple':
            result = model.objects.filter(Q(is_paid=False))
        else:
            result = model.objects.filter(Q(is_paid=False) | Q(status='toship', otherfield='FOO', anotherfield='BAR'))
        for items in result:
            ...
        

        这可能更复杂,但我相信你明白了。

        【讨论】:

        • 好的,我想我的问题是现在。假设我有一个基本上是这样的查询: model.objects.filter(Q(is_paid=False)) 我想用一些动态值向该查询添加另一个 Q 对象,以产生与您发布的查询基本相同的查询,但是它会被动态创建。这就是我在这种情况下苦苦挣扎的地方。我将如何实现这一目标?
        • 别忘了 from django.db.models import Q
        【解决方案4】:

        这是进行动态“或”查询的好方法:

        import operator
        from django.db.models import Q
        from your_app.models import your_model_object
        
        q_list = [Q(question__startswith='Who'), Q(question__startswith='What')]
        your_model_object.objects.filter(reduce(operator.or_, q_list))
        

        如果你想使用“AND”:

        your_model_object.objects.filter(reduce(operator.and_, q_list))
        

        【讨论】:

          猜你喜欢
          • 2015-06-23
          • 2013-05-19
          • 2021-09-15
          • 1970-01-01
          • 2013-12-11
          • 2017-09-16
          • 2010-12-27
          • 2014-02-06
          相关资源
          最近更新 更多