我想写一个等同于这个SQL查询的Django查询:
SELECT * from user where income >= 5000 or income is NULL.
如何构建Django查询集过滤器?
User.objects.filter(income__gte=5000, income=0)
这不起作用,因为AND
是过滤器。我想OR
过滤器来获得各个查询集的联合。
答案 0 :(得分:467)
from django.db.models import Q
User.objects.filter(Q(income__gte=5000) | Q(income__isnull=True))
答案 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%)'