Published on

[Django] Q객체를 이용해 쿼리 효율 올리기

Authors
  • avatar
    Name
    Almer Minified
    Twitter

[Django] Q객체

Q 객체란?

장고에서는 때때로

MyModel.objects.filter(somefilter=somefilter... 매우 많은 조건)

처럼 복잡한 조건을 많이 추가해야 할 때가 있다. 그리고 그 조건은 다른 조건에 의해 설정될 수 있다. 이렇게 하면 코드가 엄청나게 복잡해질 수 있다. 아래처럼말이다

queryset = MyPost.objects.filter((이경우엔=q | 저 경우엔=q) & 이 경우엔=p).order_by("-created_at")

이렇게 조건이 많아지면 그 조건마다 쿼리셋을 따로 분기하기는 어렵다. 그래서 filter내의 조건들을 분기하는 게 편리한데 그걸 가능하게 해주는 것이 Q객체이다.

쿼리 분기가 필요한 경우

아래의 코드를 보자. 이 코드에는 몇 개의 조건문이 있는데 실제 코드 할 때는 이게 10개가 넘어갈 수도 있다.

if her_friends_gender == 'female':
queryset = MyPost.objects.filter((title__icontains=q | body__icontains=q) & firend_group=g).order_by("-pk")

elif her_friends_number < 10000:
queryset = MyPost.objects.filter((title**icontains=q | body**icontains=q)).order_by("-pk")

elif her_friends_smiling == True:
queryset = MyPost.objects.filter((body\_\_isnull=q)).order_by("-pk")

이 모든 복잡성으로 인해 조건문과 옵션이 많이 생길 수 밖에 없다. 그러나 간단하게 하려고 반복을 살펴보면

queryset =
MyPost.objects.filter().order_by("-pk")

이러한 부분은 계속해서 반복되고 Q 객체를 사용하여 코드의 반복을 줄일 수 있음을 알 수 있다.

실제로 Q객체를 활용해서 줄이는 방법

Q 객체는 코드상에서 파이썬 객체 처럼 사용할 수가 있다. 예를들면

Q(title__icontains=q) | Q(body__isnull=q) & Q(friend_group=c)

이런식으로 위의 필터 안에 들어갈 코드들을 바꿀 수 있게 된다. 이제 감이 올 것이다. 또한 연산도 가능하다 | or연산과 & and 연산이 그것이다.

Q = Q()
Q |= Q(some_con=1)
Q |= Q(some_con=2)
Q &= Q(some_con=3)
Q ~= Q(some_con=3)

이런식으로 Q객체 자체에 and와 or연산, 그리고 not 연산까지도 추가할 수 있게 된다.

쿼리를 내부적으로 처리하는 원리

Django에서는 내부적으로 SQL의 Where문을 생성하게 되는데

Q(name='John') | Q(age=30)

이런 경우엔

WHERE name = 'John' OR age = 30

이런식으로 자동으로 변환시켜주는 것이다. 이 내용은 공식문서에서도 확인할 수 있다.

공식문서에서 확인