Manager와 QuerySet을 커스텀하여 재사용 가능한 쿼리 만들기

Django ORM의 Custom Manager와 Custom QuerySet을 활용하여 복잡하고 반복적인 쿼리를 모델 레벨에 캡슐화하고 재사용하는 방법

왜 Manager와 QuerySet을 커스텀해야 하는가?

안티 패턴

  • 여러 View에서 동일한 필터링 로직을 반복 작성

  • 비즈니스 로직이 View 전반에 흩어짐

  • 조건 변경 시 모든 관련 코드를 찾아 수정해야 함

개선된 패턴

  • 모델 레벨에서 재사용 가능한 쿼리 메서드 정의

  • View 로직의 간결성과 명확성 확보

  • 코드 유지보수성과 테스트 용이성 향상

Manager와 QuerySet의 관계

구분
Manager
QuerySet

역할

모델과 데이터베이스의 주요 인터페이스

체인 가능한 연산을 통한 레코드 집합 관리

반환값

대부분 QuerySet 반환

항상 QuerySet 반환

커스텀 목적

테이블 전체 작업, 기본 QuerySet 변경

체인 가능한 필터링 메서드 추가

단계별 구현

1단계: Custom QuerySet 정의

class PostQuerySet(models.QuerySet):
    def published(self):
        return self.filter(
            published_at__isnull=False,
            published_at__lte=timezone.now(),
            is_deleted=False
        )

    def with_details(self):
        return self.select_related('author').annotate(
            comment_count=Count('comments')
        )

2단계: Custom Manager 정의

class PostManager(models.Manager):
    def get_queryset(self):
        return PostQuerySet(self.model, using=self._db)

    def published(self):
        return self.get_queryset().published()

    def with_details(self):
        return self.get_queryset().with_details()

3단계: 모델에 Manager 연결

class Post(models.Model):
    # 필드 정의
    title = models.CharField(max_length=200)
    content = models.TextField()
    published_at = models.DateTimeField(null=True, blank=True)
    is_deleted = models.BooleanField(default=False)
    
    # Manager 연결
    objects = PostManager()

실무 팁 및 주의사항

get_queryset 오버라이딩 주의점

  • 기본 필터를 적용할 때 관리자 페이지에서 문제 발생 가능

  • 여러 Manager 사용으로 해결

class Post(models.Model):
    objects = models.Manager()  # 기본 Manager
    published_objects = PublishedPostManager()  # 커스텀 Manager

ViewSet에서의 활용

class PostViewSet(viewsets.ReadOnlyModelViewSet):
    serializer_class = PostSerializer

    def get_queryset(self):
        return Post.objects.published().with_details()

메서드 분류 기준

  • QuerySet 메서드: 결과물이 QuerySet인 경우, 체이닝 필요한 경우

  • Manager 메서드: 객체 생성/수정, 테이블 전체 작업하는 경우

주요 장점

  • 재사용성: 공통 쿼리 로직의 중앙 집중 관리

  • 가독성: 명확하고 직관적인 코드 작성

  • 캡슐화: 비즈니스 규칙을 모델 계층에 캡슐화

  • 테스트 용이성: 각 메서드의 독립적 유닛 테스트 가능

  • 체이닝: 직관적인 메서드 체이닝 지원

Last updated