如何在django queryset中执行OR条件?

时间:2011-07-04 06:04:16

标签: python sql django django-queryset django-orm

我想写一个等同于这个SQL查询的Django查询:

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

如何构建Django查询集过滤器?

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

这不起作用,因为AND是过滤器。我想OR过滤器来获得各个查询集的联合。

4 个答案:

答案 0 :(得分:467)

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

via Documentation

答案 1 :(得分:50)

因为QuerySets implement Python __or__运算符(|)或union,它才有效。正如您所期望的那样,|二元运算符返回QuerySet,因此order_by().distinct()和其他查询集过滤器可以添加到最后。

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

答案 2 :(得分:3)

如果有人正在寻找它,只需为附加到Q对象的多个过滤器添加它即可。 如果提供了Q 对象,则该对象必须位于任何关键字参数的定义之前。否则,它是无效的查询。这样做时要小心。

一个例子是

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

在此设置“或”条件,并考虑带有收入类别的过滤器

答案 3 :(得分:2)

在现有答案中已经提到了这两个选项:

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

q2 = User.objects.filter(income__gte=5000) | User.objects.filter(income__isnull=True)

但是,似乎似乎有些困惑。

重点是它们在SQL级别上是相同的,因此请随意选择任意一个!

Django ORM Cookbook对此进行了详细讨论,这是相关部分:


queryset = User.objects.filter(
        first_name__startswith='R'
    ) | User.objects.filter(
    last_name__startswith='D'
)

导致

In [5]: str(queryset.query)
Out[5]: 'SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login",
"auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name",
"auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff",
"auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user"
WHERE ("auth_user"."first_name"::text LIKE R% OR "auth_user"."last_name"::text LIKE D%)'

qs = User.objects.filter(Q(first_name__startswith='R') | Q(last_name__startswith='D'))

导致

In [9]: str(qs.query)
Out[9]: 'SELECT "auth_user"."id", "auth_user"."password", "auth_user"."last_login",
 "auth_user"."is_superuser", "auth_user"."username", "auth_user"."first_name",
  "auth_user"."last_name", "auth_user"."email", "auth_user"."is_staff",
  "auth_user"."is_active", "auth_user"."date_joined" FROM "auth_user"
  WHERE ("auth_user"."first_name"::text LIKE R% OR "auth_user"."last_name"::text LIKE D%)'

来源:django-orm-cookbook