Q 객체는 데이터베이스 관련 작업에서 사용할 수 있는 SQL 조건을 나타낸다. 만약 쿼리셋 조회 조건이 복잡하면 Q 객체를 사용하면 된다.
Q 객체는 모델 필드 또는 annotation의 value를 나타낸다는 점에서 F 객체와 유사한 면이 있다. 둘 다 조건을 정의하고 재사용할 수 있도록 만들어 주며 |, & operator를 이용해 각 객체를 합칠 수도 있다.
Q 객체는 키워드 인자의 집합을 캡슐화 하기 위해 사용된다. 이러한 키워드 인자는 필드 조회를 할 때 처럼 지정할 수 있다(필드 조회: fieldlookuptype=value, 예시: Entry.objects.filter(pub_datelte='date')).
아래와 같이 사용하면 LIKE 쿼리가 된다.
from django.db.models import Q
Q(question__startswith='What')
Q(question__startswith='Who') | Q(question__startswith='What')
WHERE question LIKE 'Who%' OR question LIKE 'What%'
Q 앞에 ~을 붙이면 된다. 그러면 부정의 의미를 갖게 된다.
Q(question__startswith='Who') | ~Q(pub_date__year=2005)
filter(), exclude(), get()과 같은 조회 함수에 Q를 위치 인자로 넘겨줄 수 있다.
만약 여러 개의 Q 객체 인자를 조회 함수에 넘겨 주면 각 인자는 and로 연결 된다.
Poll.objects.get(
Q(question__startswith='Who'),
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)
SELECT * from polls WHERE question LIKE 'Who%'
AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')
조회 함수에서 Q 객체와 키워드 인자를 함께 사용할 때는 Q 객체를 키워드 인자보다 더 앞에 위치 시켜야 한다. 그래야 유효한 조회가 가능하다. 순서가 반대가 되면 유효하지 않다.
Poll.objects.get(
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
question__startswith='Who',
)
추가로, 아래와 같이 Case When 구문안에서 사용하는 것도 가능하다.
Poll.objects.annotate(
something=Case(
When(
Q(poll__name___isnull=False)
& Q(poll__last_voted__gte=base_dt),
then=True,
),
default=False,
output_field=BooleanField(),
)
)