我想写一个Django查询等价于下面的SQL查询:

SELECT * from user where income >= 5000 or income is NULL.

如何构造Django queryset过滤器?

User.objects.filter(income__gte=5000, income=0)

这行不通,因为它和过滤器。我想对过滤器进行OR操作以获得单个查询集的并集。


当前回答

因为QuerySets实现了Python __or__操作符(|)或联合,所以它可以工作。正如您所期望的那样,|二进制操作符返回一个QuerySet,因此order_by()、.distinct()和其他QuerySet过滤器可以附加到末尾。

combined_queryset = User.objects.filter(income__gte=5000) | User.objects.filter(income__isnull=True)
ordered_queryset = combined_queryset.order_by('-income')

更新2019-06-20:现在在Django 2.1 QuerySet API参考中有完整的文档。更多历史性的讨论可以在DjangoProject票号21333中找到。

其他回答

类似于@lprsd的答案,你可以使用or_ from操作符库:

from operator import or_
from django.db.models import Q

User.objects.filter(or_(Q(income__gte=5000), Q(income__isnull=True)))

操作符。Or_得到两个值作为参数。要使用三个(或更多)语句,请使用reduce:

from operator import or_
from functools import reduce
from django.db.models import Q

User.objects.filter(reduce(or_, Q(income__gte=5000), Q(income__lt=300), Q(income__isnull=True)))

这种解决方案对于动态生成的查询(例如,使用前端输入的自定义参数)非常有用。

细节

Operator和functools是python标准库,这意味着你不需要安装它们。

正如你在or_函数的文档字符串中看到的,对于a和b参数,它是

和|b一样。

和减少:

将两个参数的函数累加到序列项上, 从左到右,从而将序列简化为单个值。

只是添加这个附加到Q对象的多个过滤器,如果有人可能会寻找它。 如果提供了Q对象,它必须在任何关键字参数的定义之前。否则它是一个无效的查询。你做这件事的时候要小心。

一个例子是

from django.db.models import Q
User.objects.filter(Q(income__gte=5000) | Q(income__isnull=True),category='income')

这里考虑了OR条件和带有收入类别的过滤器

因为QuerySets实现了Python __or__操作符(|)或联合,所以它可以工作。正如您所期望的那样,|二进制操作符返回一个QuerySet,因此order_by()、.distinct()和其他QuerySet过滤器可以附加到末尾。

combined_queryset = User.objects.filter(income__gte=5000) | User.objects.filter(income__isnull=True)
ordered_queryset = combined_queryset.order_by('-income')

更新2019-06-20:现在在Django 2.1 QuerySet API参考中有完整的文档。更多历史性的讨论可以在DjangoProject票号21333中找到。

为了添加像“OR”或“AND”这样的条件,就像我们在sql查询中使用的那样,我们有这样的方法作为示例

from django.db.models import Q
Poll.objects.get(Q(question__startswith='Who'),Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))

这相当于这个SQL查询

SELECT * from polls WHERE question LIKE 'Who%'
AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')

我希望你能够正确地理解,“,”是“与”操作符,而“|”是django中使用的“或”操作符。

from django.db.models import Q
User.objects.filter(Q(income__gte=5000) | Q(income__isnull=True))

通过文档