我根据是否设置了变量以及'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)
答案 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=4
或type=5
或status=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)
如果一个status
为OR
而另一个status
为AND
,请记住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)