代码之家  ›  专栏  ›  技术社区  ›  Bartek

使用filter()和q对象组合的django orm查询

  •  4
  • Bartek  · 技术社区  · 16 年前

    我希望创建一个稍微复杂一点的查询,它可以很容易地使用原始SQL编写。以下是原始查询的示例:

    从销售中选择我的,字段,其中“U paid=false或status='toship'、otherfield='foo'和anotherfield='bar'

    这很简单,它会生成所有paid=false的结果,然后为my和matches生成第二个结果集。

    现在我知道了Q对象,我知道了过滤,但我似乎无法将我的思想集中在如何在django ORM中清晰地实现这一点上。

    有什么小窍门吗?

    谢谢

    4 回复  |  直到 8 年前
        1
  •  21
  •   tarequeh    16 年前

    您可以继续以某种动态方式构建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
  •  13
  •   Daniel Roseman    16 年前

    虽然googletorp是对的,您不能用字符串动态构造查询,但是 可以 使用字典参数。类似:

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

    其中mydict1和2的形式为:

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

    等。

        3
  •  2
  •   googletorp    16 年前

    这样的方法应该有效:

    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:
        ...
    

    这可能更复杂,但我相信你会理解的。

        4
  •  2
  •   elad silver    8 年前

    这是一种执行动态“或”查询的好方法:

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