-
[Django] Custom Manager, Custom QuerySet언어/파이썬 & 장고 2019. 2. 2. 18:12
Django 모델에서 Manager는 데이터베이스와 상호 작용하는 인터페이스입니다. 기본적으로 Manager는 Model.objects 속성을 통해 사용할 수 있습니다. Django 모델마다 기본적으로 사용되는 기본 관리자는 django.db.models.Manager입니다.
from django.db import models class DocumentManager(models.Manager): def pdfs(self): return self.filter(file_type='pdf') def smaller_than(self, size): return self.filter(size__lt=size) class Document(models.Model): name = models.CharField(max_length=30) size = models.PositiveIntegerField(default=0) file_type = models.CharField(max_length=10, blank=True) objects = DocumentManager()
위 예시에서 filter_type='pdf'를 선언하는 방법은 아래와 같습니다. 또한 호출 후, filter()와 order_by()같이 추가적으로 연결하여 사용할 수 있습니다.
Document.objects.pdfs() Document.objects.pdfs().filter(name='test') Document.objects.pdfs().order_by('name')
하지만 Manager에 선언한 다른 메소드를 호출하고자 하면 오류가 발생합니다.
Document.objects.pdfs().smaller_than(1000) # AttributeError: 'QuerySet' object has no attribute 'smaller_than'
이 문제를 해결하는 것은 Custom QuerySet을 선언하는 것입니다.
class DocumentQuerySet(models.QuerySet): def pdfs(self): return self.filter(file_type='pdf') def smaller_than(self, size): return self.filter(size__lt=size) class DocumentManager(models.Manager): def get_queryset(self): return DocumentQuerySet(self.model, using=self._db) # 중요 def pdfs(self): return self.get_queryset().pdfs() def smaller_than(self, size): return self.get_queryset().smaller_than(size) class Document(models.Model): name = models.CharField(max_length=30) size = models.PositiveIntegerField(default=0) file_type = models.CharField(max_length=10, blank=True) objects = DocumentManager() Document.objects.pdfs().smaller_than(1000).exclude(name='Article').order_by('name')
만약 Custom QuerySet만 정의하고자 하면 아래와 같이 선언하면 됩니다.
class DocumentQuerySet(models.QuerySet): def pdfs(self): return self.filter(file_type='pdf') def smaller_than(self, size): return self.filter(size__lt=size) class Document(models.Model): name = models.CharField(max_length=30) size = models.PositiveIntegerField(default=0) file_type = models.CharField(max_length=10, blank=True) objects = DocumentQuerySet.as_manager()
pdfs()만 호출할 수 있는 것은 물론, smaller_than() 또한 연결하여 호출할 수 있습니다.
Document.objects.pdfs().smaller_than(1000)
models.py 안에 조회 쿼리를 넣을 수 있지만 코드가 커진다면 Manager와 QuerySet을 managers.py라는 다른 모듈에 유지하는 것을 추천합니다. Custom Manager와 Custom QuerySet을 사용하는 이점은 공통적으로 사용되는 쿼리를 공통 함수로 정의할 수 있고 실제 동작을 숨길 수 있습니다.