-
Django Manager, Queryset기술/Django 2021. 9. 24. 18:51
Django 에서 ORM 을 깔끔하게 사용할 수 있는 공식적인 방법 두가지가 있는데
언제 어떻게 사용해야하는지에 대한 명확한 기준이 없어 고민하게 되었을 때 찾은 글입니다.
Manager
Django 는 Manager 를 통해 데이터베이스와 통신합니다. 응용프로그램과 데이터베이스 사이의 일종의 통신 게이트입니다. 따라서 모든 장고의 모델은 하나 이상의 Manager 가 존재합니다.
Custom Manager 를 언제 사용하나요?
1. 초기 Queryset 을 수정하기 위한 목적
만약 Manager 에 따라 삭제된 것을 포함/미포함하여 가져오고 싶을 때,
Manager 를 사용하여 첫 Queryset 에서 필터해서 가져오게 할 수 있습니다.
from django.db import models class PostManager(models.Manager): """삭제된 Post 는 제외하고 가져오는 Manager""" def get_queryset(self): return super().get_queryset().filter(deleted__isnull=True) class AllPostManager(models.Manager): """삭제된 Post 도 포함하여 가져오는 Manager""" pass class Post(models.Model): deleted = models.DateTiemField(blank=True, null=True) objects = PostManager() all_objects = AllPostManager()
2. 테이블 단위의 기능 추가하기 위한 목적
모델에 테이블 단위의 기능을 추가하고 싶을 때 사용합니다.
행 단위의 경우 모델의 메서드를 통해 제공할 수 있습니다.
Manager 메서드는 Queryset 의 형태 뿐만아니라 int, string, dict 등 어떤 형태의 것도 리턴할 수 있습니다.
from django.db import models class PostManager(models.Manager): def publish_count(self): """Post 중 publish 된 것의 개수를 리턴하는 메서드""" return self.get_queryset().filter(publish__isnull=False).count() # 아래와 같이 사용 가능합니다. # Post.objects.publish_count()
Queryset
Manager 에서 정의한 메서드는 체인하여 사용할 수 없기 때문에 만약 체인하여 쿼리셋을 수정해야 할 경우에는 Queryset 을 사용해야합니다.
from django.db import models. class PostQueryset(models.Queryset): def publish(self): """Post 중 publish 된 쿼리셋을 리턴하는 메서드""" return self.filter(publish__isnull=False) def important(self): """important 가 붙어있는 쿼리셋을 리턴하는 메서드""" return self.filter(important=True) # 아래와 같이 사용 가능합니다. # Post.objects.publish().important()
개인적인 생각
Custom Manager 는 다양한 데이터 사용을 구분하는데 사용되며 Custom Queryset 은 반복을 막는 목적으로 사용하는 것 같습니다.
모든 Queryset 메서드는 복사되어 Manager 의 메서드로서 사용할 수 있습니다.
get_or_create 은 체이닝 되지 않지만 Queryset 에 정의되어 있는 메서드입니다.
즉, 초기 데이터 필터를 위해서는 Manager 를 커스텀하고
DRY 를 지키기 위해서는 중복되는 로직은 Queryset 에 작성한다고 생각하고 현재 사용중입니다.
참고
'기술 > Django' 카테고리의 다른 글
Django Filters 에서 하나의 Key를 가지고 여러 값 필터하기 ( MultipleFilter ) (0) 2021.09.24 Django 에서 String datetime 을 aware 한 datetime 으로 변경하는 방법 (0) 2021.09.24 Django 에서 Chain 필터 시 추가적인 테이블 JOIN 방지하기 ( + _next_is_sticky ) (0) 2021.09.24 Django 에서 Annotate 와 Union 을 함께 사용할 때 생기는 문제 (0) 2021.09.24 Django 에서 Generic ForeignKey 를 사용을 권장하지 않는 이유 (0) 2021.09.24