django queryset에서 OR 조건을 수행하는 방법은 무엇입니까?


294

이 SQL 쿼리와 동등한 Django 쿼리를 작성하고 싶습니다.

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

Django 쿼리 세트 필터를 구성하는 방법은 무엇입니까?

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

AND필터 이기 때문에 작동하지 않습니다 . OR개별 쿼리 집합을 통합하기 위해 필터를 원합니다 .


답변:


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

설명서를 통해


object.query의 인쇄를 추가하면 ORM 및 Query 출력과 관련하여 익숙해 질 수 있습니다. BTW 좋은 예입니다.
Eddwin Paz

이 유형의 쿼리를 사용하거나 두 개의 개별 쿼리를 수행하는 것이 더 낫습니까?
MHB

60

때문에 검색어 세트 구현 파이썬 __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-06-20 업데이트 : 이제 Django 2.1 QuerySet API 참조 서 에 완전히 설명되어 있습니다. 더 역사적인 토론은 DjangoProject 티켓 번호 21333 에서 찾을 수 있습니다 .


18
"미등록"과 "레거시"는 나를 두렵게한다. 여기에 허용 된 답변에 자세히 설명 된 것처럼 Q 객체를 사용하는 것이 더 안전하다고 생각합니다.
0atman

2
참고로, order_by () 및 distinct ()는 파이프 된
쿼리 세트

@carruthd 감사합니다. 나는 이것도 확인했다. 윌 편집
호브

order_by ()를 각 개별 쿼리 집합에 적용한 다음 결합 할 수 있습니까? 각 조건의 순서가 여전히 유지되도록? 예를 들면 다음과 같습니다. combination_queryset = User.objects.filter (income__gte = 5000) .order_by ( 'income') | User.objects.filter (income__lt = 5000) .order_by ( '-income')?
교착 상태

2
@ 오트 만 : | 운영자가 문서화되었습니다. docs.djangoproject.com/en/2.0/ref/models/querysets 참조 : "일반적으로 Q () 객체를 사용하면 조건을 정의하고 재사용 할 수 있습니다.이를 통해 | (OR) 및 & ( AND) 연산자, 특히 QuerySet에서 OR을 사용할 수 없습니다. " 이전 버전의 문서는 확인하지 않았지만 파이프 연산자는 적어도 장고 1.1.4에서 작동합니다 (방금 시도했습니다).
makeroo

10

두 가지 옵션 모두 기존 답변에 이미 언급되어 있습니다.

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 수준 에서 동일 하므로 원하는 것을 자유롭게 선택하십시오!

장고 ORM 요리 책은 여기,이에 대한 몇 가지 구체적으로 이야기 관련 부분입니다 :


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


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.