(참고: stackoverflow.com/questions/18235419/how-to-chain-django-querysets-preserving-individual-order)
쿼리셋을 여러개를 만들어서 만드는 순서대로 합쳐 리스트를 만들고 반환해야 되는 때를 가정해봅시다. 데이터베이스에 딱 1번만 접근하면서, 쿼리셋을 만드는 순서 == 실제로 반환되는 모델의 순서가 되도록 해야 한다고 생각해봅시다.
>>> qs1.union(qs2, qs3)
1. SQL의 UNION operator를 사용하도록 QuerySet.union을 사용한다
db 접근은 한번만 합니다. 문제는 합쳐지는 쿼리셋의 순서가 보장되지 않습니다
result = []
result.append(qs1.first())
result.append(qs2.first())
2. 쿼리셋을 미리 evaluation 해놓고 리스트에 추가한다
순서는 보장되지만 db 히트 수가 많아집니다
q1 = Q(...)
q2 = Q(...)
q3 = Q(...)
qs = (Model.objects
.filter(q1 | q2 | q3)
.annotate(
search_type_ordering=Case(
When(q1, then=Value(2)),
When(q2, then=Value(1)),
When(q3, then=Value(0)),
default=Value(-1),
output_field=IntegerField()))
.order_by('-search_type_ordering', ...))
3. annotate로 정렬할 필드를 추가한다
db 히트도 한번이고, 순서도 보장됩니다.
더 좋은 방안이나 의견이 있으시면 댓글 부탁드립니다 (장고뉴비입니다 ㅠ)
반응형
'프로그래밍 > Python' 카테고리의 다른 글
[Django] Proxy model도 마이그레이션이 필요하다 (0) | 2021.02.20 |
---|---|
[Django] 모델의 clean()이 자동으로 호출되지 않는 이유 (0) | 2021.02.12 |
[Django] BinaryField로부터 파일을 직접 서비스하면 안되는 이유 (0) | 2021.01.16 |
[Python] dict를 복사하면서 특정 필드를 빼고 복사하는 법 (0) | 2021.01.13 |
[Python] enum value로 @dataclass 사용하기 (0) | 2021.01.13 |