개발기록장

[Django] Q객체를 이용한 ORM 조건절 본문

TIL/Django

[Django] Q객체를 이용한 ORM 조건절

yangahh 2021. 2. 28. 22:14

 

Django에서 QuerySet 조회 조건이 복잡할 때 Q객체를 사용하면 간결하게 코드를 작성할 수 있다.


Q객체 사용하기

 

- import

Q객체는 Django 내장 모듈로 사용하려면 먼저 import를 해야한다.

from django.db.models import Q

 

 

- AND 연산, OR 연산

## AND
# ex) first_name이 'a'로 시작하거나 last_name이 'b'로 시작하는 객체를 조회 (아래 두 코드는 동일하다)

User.objects.filter(Q(first_name__startswith='a') & Q(last_name__startswith='b'))

User.objects.filter(first_name__startswith='a', last_name__startswith='b')


## OR
# ex) first_name이 'a'로 시작하거나 last_name이 'b'로 시작하는 객체를 조회

User.objects.filter(Q(first_name__startswith='a') | Q(last_name__startswith='b'))

사실 AND 연산은 filter()내에서 그냥 조건들을 , 로 연결하여 사용하는 것과 같다.
하지만 OR 연산은 위와 같이 Q객체와 | 를 사용하면 코드 길이를 줄이고 가독성도 높일 수 있다.

 

 

- NOT 연산

# ex) first_name이 'a'로 시작하는 것을 제외한 객체 조회
User.objects.filtera(~Q(first_name__startswith='a'))

User.objects.exclude(first_name__startswith='a')

NOT 연산은 Q객체 앞에 ~를 사용하여 쓸 수 있다.

 

 

- 조건 연결하기

q = Q()

q.add(Q(age=30), q.OR)
q.add(Q(last_name='kim') | Q(last_name='lee'), q.AND)
q.add(~Q(first_name__startswith='a'), q.AND)

User.objects.filter(q)

첫 번째 줄과 같이 빈 Q객체를 먼저 선언할 수 도 있다.

첫 번째 Q객체를 선언한 이후에 .add()메소드로 여러 개의 Q객체를 연결시킬 수 있다.

.add()에서 두 번째 인자에 앞의 Q객체와 연결될 때 어떤 연산자로 연결할지를 써주면 된다.

위 예시를 SQL로 작성하면 아래와 같다.

# 위와 동일한 결과

select * 
  from user
 where age=30 and (last_name='kim' or last_name='lee') and first_name not like 'a%';