본문 바로가기
Programing/django

Django Model Aggregate

by Tomining 2016. 8. 19.
Django 는 DB 쿼리를 수행할 때, ORM 방식을 사용합니다.
주로 sql 을 직접 작성해 왔기 때문에 익숙하지 않아 기본적인 쿼리도 장시간의 검색을 통해 사용하곤 했는데요.
최근에 model 의 aggregate 기능을 사용해 본 사례를 글로 작성해 보았습니다.

들어가며...

Django 로 개발을 진행하면서 특정 테이블의 한 컬럼에서 Max 값을 가져와야 할 일이 생겼습니다.
SQL 로 생성하면 SELECT MAX(SEQ) FROM USER 로 작성하면 되지만 ORM 방식인 django model 에서는 어떻게 구현해야 하는지 몰랐습니다.

Aggregate


보통 django query 는 CRUD(create, retrieve, update, delete) 작업에 사용합니다. 하지만 때론 sum(), max() 같은 쿼리도 수행할 때가 있는데요.
이 때 사용할 수 있는 것이 django model 에 있는 aggregate 입니다.

아래 코드는 django 공식 페이지에 나와있는 예제 코드입니다.

# Total number of books.
>>> Book.objects.count()
2452

# Total number of books with publisher=BaloneyPress
>>> Book.objects.filter(publisher__name='BaloneyPress').count()
73

# Average price across all books.
>>> from django.db.models import Avg
>>> Book.objects.all().aggregate(Avg('price'))
{'price__avg'34.35}

# Max price across all books.
>>> from django.db.models import Max
>>> Book.objects.all().aggregate(Max('price'))
{'price__max': Decimal('81.20')}

# Cost per page
>>> from django.db.models import F, FloatField, Sum
>>> Book.objects.all().aggregate(
...    price_per_page=Sum(F('price')/F('pages'), output_field=FloatField()))
{'price_per_page'0.4470664529184653}

# All the following queries involve traversing the Book<->Publisher
# foreign key relationship backwards.

# Each publisher, each with a count of books as a "num_books" attribute.
>>> from django.db.models import Count
>>> pubs = Publisher.objects.annotate(num_books=Count('book'))
>>> pubs
<QuerySet [<Publisher: BaloneyPress><Publisher: SalamiPress>...]>
>>> pubs[0].num_books
73

# The top 5 publishers, in order by number of books.
>>> pubs = Publisher.objects.annotate(num_books=Count('book')).order_by('-num_books')[:5]
>>> pubs[0].num_books
1323

Max() 를 예로 코딩해 보았습니다.
예를들어 USER 테이블에 신규 사용자 정보를 저장하기 위해 SEQ 컬럼을 MAX 값에서 +1 을 하고자 합니다.
이 때 aggregate 를 사용하여 아래와 같이 할 수 있습니다.

User.objects.all().aggregate(Max(‘seq’))[‘seq__max’] + 1
SELECT MAX(SEQ) + 1
FROM USER

한 줄로 간단하게 할 수 있습니다.
(NVL 처리는 하지 않았습니다. 실제 Production Level 에서는 NVL 처리를 하셔야 합니다.)

위에서 언급된 기능 외에도 aggregate 에는 많은 기능들이 있습니다. django 공식 문서를 참고하시면 좀 더 자세히 알 수 있습니다.


참고

'Programing > django' 카테고리의 다른 글

auto_now VS auto_now_add  (0) 2016.08.19
Django 기초 스터디 자료  (0) 2016.04.04