Django条件查询:我该如何避免这种情况?

时间:2014-09-15 14:20:50

标签: python django conditional

我根据是否设置了变量以及'doc_type'的值来进行多个条件查询。但我觉得它看起来很难看,我正在重复编码。 是否有更清晰的方法来完成这项工作?

if status is not None:
    if doc_type == 4:
        invoices = Invoice.objects.filter(Q(type=4) | Q(type=5) | Q(status=status))
    else:
        invoices = Invoice.objects.filter(type=doc_type, status=status)
else:
    if doc_type == 4:
        invoices = Invoice.objects.filter(Q(type=4) | Q(type=5))
    else:
        invoices = Invoice.objects.filter(type=doc_type)

3 个答案:

答案 0 :(得分:4)

Q objects可以使用|&组合。

使用operator.or_|)和operator.and_&)作为函数而不是运算符,代码可以表示为:

import operator

op = operator.and_
q = Q(type=doc_type)  # This is always included.
if doc_type == 4:
    # When doc_type == 4, conditions are combine with `|`, otherwise `&`
    op = operator.or_
    q = Q(type=doc_type) | Q(type=5)

if status is not None:
    q = op(q, status=status)

invoices = Invoice.objects.filter(q)

答案 1 :(得分:4)

你确定这是你想要的吗?

    invoices = Invoice.objects.filter(Q(type=4) | Q(type=5) | Q(status=status))

这将返回type=4type=5status=Status的所有发票。

我认为你的意思是(类型是4或5) AND status = status?如果是这样,您可以按如下方式进行查询:

types = [doc_type]
if doc_type == 4:
    types.append(5)
invoices = Invoice.objects.filter(type__in=types)
if status is not None:
    invoices = invoices.filter(status=status)

如果您愿意,可以使用Q()个对象,但我认为在这种情况下链接过滤器更容易理解。

答案 2 :(得分:0)

如果一个statusOR而另一个statusAND,请记住QuerySet支持|&

qs = Invoice.objects.filter(doc_type__in=(doc_type, 5) if doc_type == 4 else (doc_type,))
if status is not None:
    if doc_type == 4:
        qs |= Invoice.objects.filter(status=status)
    else:
        qs = qs.filter(status=status)