Manager는 Django 모델에 데이터베이스 쿼리작업을 제공하는 인터페이스입니다.
Django 응용프로그램의 모든 모델에는 최소 하나 이상의 Manager가 있습니다.
기본적으로 Django는 모든 Django 모델 클래스에 objects 라는 이름의 Manager를 추가합니다.
그러나, 객체 필드를 이름으로 사용하거나 Manager용 객체 이외의 이름을 사용하려는 경우에는 모델별로 이름을 변경할 수 있습니다.
주어진 클래스에 대해 Manager의 이름을 바꾸려면, 해당 모델에서 models.Manager() 유형을 클래스 속성을 정의하십시오.
from django.db import models class Person(models.Model): #... people = models.Manager()
기본 Manager 클래스를 확장하고 모델에서 사용자 정의 Manager를 인스턴스화 하여 특정 모델에서 사용자 정의 Manager를 사용 할 수 있습니다.
사용자 정의 Manager를 사용하는 이유는 2가지가 있습니다.
Manager 메소드를 추가하거나 Manager가 반환하는 초기 QuerySet을 수정하는 이유입니다.
[대표적인 예]
class PostManager(models.Manager):
def active(self, *args, **kwargs):
# Post.objects.all() = super(PostManager, self).all()
return super(PostManager, self).filter(draft=False).filter(publish__lte=timezone.now())
추가 관리자에 메서드 추가하기
우선은 모델에 "테이블 수준"의 기능을 추가하고 싶을 때 사용할 수 있습니다.
행 수준의 기능을 추가할때는 Model 메소드를 사용하십시오 여기서는 컬럼기준일떄 이야기합니다.
사용자 정의 관리자 메소드는 원하는 모든 것을 리턴 할 수 있습니다. QuerySet을 리턴할 필요는 없습니다.
예를 들어, 사용자 정의 관리자는 모든 OpinionPoll 객체의 목록을 반환하는 with_counts() 메서드를 제공합니다.
그런데 각 쿼리에는 집계 쿼리의 결과인 num_responses 속성이 추가로 있습니다.
from django.db import models class PollManager(models.Manager): def with_counts(self): from django.db import connection with connection.cursor() as cursor: cursor.execute(""" SELECT p.id, p.question, p.poll_date, COUNT(*) FROM polls_opinionpoll p, polls_response r WHERE p.id = r.poll_id GROUP BY p.id, p.question, p.poll_date ORDER BY p.poll_date DESC""") result_list = [] for row in cursor.fetchall(): p = self.model(id=row[0], question=row[1], poll_date=row[2]) p.num_responses = row[3] result_list.append(p) return result_list class OpinionPoll(models.Model): question = models.CharField(max_length=200) poll_date = models.DateField() objects = PollManager() class Response(models.Model): poll = models.ForeignKey(OpinionPoll, on_delete=models.CASCADE) person_name = models.CharField(max_length=50) response = models.TextField()
이 예제에서는 OpinionPool.objects.with_counts() 를 사용해서 num_responses 속성을 가지는 OpinionPoll 객체의 목록을 반환합니다.
관리자의 기본 QuerySet은 시스템의 모든 객체를 반환합니다.
예를들어 이런 모델이 있다고 가정합시다.
from django.db import models class Book(models.Model): title = models.CharField(max_length=100) author = models.CharField(max_length=50)
Book.objects.all() 문은 데이터베이스의 모든 책을 반환합니다.
Manager.get_queryset() 메서드를 재정의 해서 Manager의 기본 QuerySet을 재정의 할 수 있습니다.
get_queryset()은 QuerySet을 반환해야만 합니다.
예를들어 다음 모델에는 두개의 관리자가 있고, 하나는 모든 객체를 반환하고 하나는 Roald Dahl책만 반환합니다.
# First, define the Manager subclass. class DahlBookManager(models.Manager): def get_queryset(self): return super(DahlBookManager, self).get_queryset().filter(author='Roald Dahl') # Then hook it into the Book model explicitly. class Book(models.Model): title = models.CharField(max_length=100) author = models.CharField(max_length=50) objects = models.Manager() # The default manager. dahl_objects = DahlBookManager() # The Dahl-specific manager.
이 샘플 모델을 사용하면 Book.objects.all()은 데이터베이스의 모든책을 반환하지만, Book.dahl_objects.all()은 Roald Dahl이 작성한 책만 반환합니다.
물론 get_queryset()은 QuerySet 객체를 반환하기 때문에 filter(), exclude() 및 기타 모든 QuerySet 메서드를 사용 할 수 있습니다.
Book.dahl_objects.all() Book.dahl_objects.filter(title='Matilda') Book.dahl_objects.count()
그리고 하나의 모델에서 여러관리자를 사용 할 수 있다에 주목해주세요
모델에 원하는 만큼의 Manager() 인스턴스를 첨부할 수 있습니다. 이렇게하면 모델에 대한 일반적인 "필터"를 쉽게 정의 할 수 있습니다.
예제입니다.
class AuthorManager(models.Manager): def get_queryset(self): return super(AuthorManager, self).get_queryset().filter(role='A') class EditorManager(models.Manager): def get_queryset(self): return super(EditorManager, self).get_queryset().filter(role='E') class Person(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) role = models.CharField(max_length=1, choices=(('A', _('Author')), ('E', _('Editor')))) people = models.Manager() authors = AuthorManager() editors = EditorManager()
이 예제에서는 Person.authors.all(), Person.editors.all() 및 Person.people.all()을 요청하여 예측 가능한 결과를 얻을 수 있습니다.
'Python > Django' 카테고리의 다른 글
[Django] Abstract base class, Multi-table 상속, Proxy Model (0) | 2017.04.04 |
---|---|
[Django]Coding Style (0) | 2017.04.03 |
[Django] RestfulFramework - Permission (0) | 2017.03.13 |
[Django] RestFrameWork 튜토리얼 - 3. 클래스 base View (0) | 2017.03.10 |
[Django] RestFrameWork 튜토리얼 - 2. Request와 Response (0) | 2017.03.10 |