annotate()
메서드는 Django 쿼리셋에서 사용되는 함수 중 하나로, 데이터베이스에서 집계된 값을 추가하는 데 사용됩니다. annotate()
메서드를 사용하면 원하는 필드 값을 가져오고 그 값을 기반으로 새로운 필드를 생성할 수 있습니다.
annotate(aggregate_expression, ...)
aggregate_expression
: 필드 값을 계산하기 위한 집계 식을 지정합니다. 일반적으로 Django의django.db.models
모듈에 있는 집계 함수들을 사용합니다. 예를 들어,Count()
,Sum()
,Avg()
,Min()
,Max()
등이 있습니다.
annotate()
메서드는 쿼리셋의 결과에 대해 각 필드 값에 대한 집계를 수행하고, 결과에 추가된 필드를 포함한 새로운 쿼리셋을 반환합니다. 이를 통해 집계된 값을 활용할 수 있습니다.
예
Book 모델이 있다고 가정하고, 이 모델은 다음과 같은 필드가 있다고 가정하겠습니다.(title, author, pages)
이때 각 저자가 쓴 책들의 총 페이지 수를 계산한다면 아래처럼 사용할 수 있습니다.
from django.db.models import Sum # 집계 함수
total_pages_by_author = Book.objects.values("author").annotate(Sum("pages"))
이러면 각 저자별로 책들의 총 페이지 수를 계산하고 그 결과를 pages__sum
이라는 이름의 필드로 추가합니다. 그러면 각 저자의 이름과 그 저자의 책들의 총 페이지 수를 담은 딕셔너리의 쿼리셋을 리턴합니다.
리턴되는 쿼리셋의 예시는 아래와 같습니다.
total_pages_by_author = [
{
'author': 1, # 작가1의 id
'pages__sum': 250, # 작가1이 쓴 책들의 페이지 수 합산
},
{
'author': 2, # 작가2의 id
'pages__sum': 400, # 작가2가 쓴 책들의 페이지 수 합산
}
]
만약 pages__sum
이라는 필드명이 아닌 사용자가 정의한 필드명으로 구현하고 싶다면 아래 방식대로 구현하면 됩니다.
annotate(field_name=aggregate_expression)
field_name
: 생성된 필드의 이름을 지정합니다.
예
from django.db.models import Sum
total_pages_by_author = Book.objects.values("author").annotate(total_pages=Sum("pages"))
이러면 리턴값에 추가되는 필드명이 total_pages
가 됩니다.
리턴되는 쿼리셋의 예시는 아래와 같습니다.
total_pages_by_author = [
{
'author': 1, # 작가1의 id
'total_pages': 250, # 작가1이 쓴 책들의 페이지 수 합산
},
{
'author': 2, # 작가2의 id
'total_pages': 400, # 작가2가 쓴 책들의 페이지 수 합산
}
]
가변 키워드 인자
이 annotate() 함수를 공부하면서 의아한 점이 생겼습니다. anootate() 함수의 field_name
은 어떤 인자인지가 궁금해졌습니다. 키워드 인자도 아니고 위치 인자도 아니고 지정한 이름에 따라 바뀌는 인자가 무엇이지 찾아보며 알게 된 결론은 "가변 키워드 인자"였습니다.
참고로 아래 두 링크를 읽고 오시면 다음 내용이 더 이해가 잘 되실겁니다.
위치 인자와 키워드 인자 : https://yesaroun.tistory.com/entry/Python-%EC%9C%84%EC%B9%98-%EC%9D%B8%EC%9E%90-%ED%82%A4%EC%9B%8C%EB%93%9C-%EC%9D%B8%EC%9E%90
django에서 *args, **kwargs : https://yesaroun.tistory.com/entry/django%EC%97%90%EC%84%9C-args-kwargs
annotate()
는 키워드 인자를 받아서 새로운 필드 이름으로 사용하는 "키워드 인자 패킹"이라는 Python의 기능을 사용합니다.
아래의 예시가 가변 키워드 인자를 사용하는 예시입니다.
def func(**kwargs):
for key, value in kwargs.items():
print(f"{key} = {value}")
func(a=1, b=2)
# a = 1
# b = 2
이 예시는 단순하게 **kwargs
인자를 설명하는 예시일 수 있습니다. 하지만 이 예시 대로 annotate() 메서드의 가변 키워드 인자도 동일하게 동작합니다.
아래는 annotate()
에서 사용되는 가변 키워드 인자 개념을 보기 쉽게 표현한 annotate_func()
코드입니다.
def annotate_func(**kwargs):
# 이 경우 kwargs = {"total_pages": Sum("pages")}
aggregates = kwargs # 집계 표현식을 저장하는 딕셔너리
for field, aggregate_expr in aggregates.items():
# 각 키와 값을 출력합니다.
print(f"필드명: {field}, 집계 표현식: {aggregate_expr}")
annotate_func(total_pages="Sum('pages')")
# 필드명: total_pages, 집계 표현식: Sum('pages')
만약 더 django의 annotate() 메소드 코드를 보고 싶으면 아래 코드를 확인해 주세요.
django 코드 링크 : https://github.com/django/django/blob/3.2/django/db/models/query.py
'Python > Django' 카테고리의 다른 글
Django에서의 Transactions (0) | 2023.08.26 |
---|---|
values_list() (0) | 2023.08.09 |
django에서 *args, **kwargs (0) | 2023.07.25 |
get_user_model() (0) | 2023.07.22 |
django 템플릿 <script>태그 (0) | 2023.07.08 |