[英]How to perform OR condition in django queryset?
我想寫一個 Django 查詢等同於這個 SQL 查詢:
SELECT * from user where income >= 5000 or income is NULL.
如何構建 Django 查詢集過濾器?
User.objects.filter(income__gte=5000, income=0)
這不起作用,因為它AND
s 過濾器。 我想對過濾器進行OR
操作以獲得單個查詢集的並集。
from django.db.models import Q
User.objects.filter(Q(income__gte=5000) | Q(income__isnull=True))
因為QuerySet 實現了 Python __or__
運算符 ( |
) 或聯合,所以它可以正常工作。 如您所料, |
二元運算符返回一個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')
2019 年 6 月 20 日更新:這已在Django 2.1 QuerySet API 參考中完整記錄。 更多歷史討論可以在DjangoProject ticket #21333中找到。
現有答案中已經提到了這兩個選項:
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%)'
如果有人可能正在尋找它,只需為附加到Q
object 的多個過濾器添加這個。 如果提供了Q
object,則它必須位於任何關鍵字 arguments 的定義之前。 否則它是一個無效的查詢。 做的時候你應該小心。
一個例子是
from django.db.models import Q
User.objects.filter(Q(income__gte=5000) | Q(income__isnull=True),category='income')
這里考慮了 OR 條件和具有收入類別的過濾器
為了添加我們在 sql 查詢中使用的“OR”或“AND”之類的條件,我們以這種方式為例
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')
我希望您能夠正確理解“,”用於“AND”運算符和“|” 用於 django 中使用的“或”運算符。
與@lprsd 的回答類似,您可以使用operator
庫中的or_
:
from operator import or_
from django.db.models import Q
User.objects.filter(or_(Q(income__gte=5000), Q(income__isnull=True)))
operator.or_
得到兩個值 arguments。要使用三個語句(或更多)使用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_
function 的文檔字符串中看到的那樣,對於a
和b
arguments,它是
與 | 相同 b.
並reduce
:
將兩個arguments中的function累加到序列的各項中,從左到右,使序列化為單值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.