Angular, Blockchain, Science とか

Angular, Blockchain, Science全般 の情報を主に書いていきます。

Django Model Manager について

gitでいろいろコードを見ていてManagerのところで詰まったので。Managerについてまとめてみる。

参照
djangobook.com


それぞれのDjangoのModelは最低一つのmanagerをデータベースのアクセスの仕方をカスタマイズするために持ちます。
カスタムmanagerを作るのは、managerメソッドを追加するため、managerが返す初期のクエリセット編修するための2つです。

まずmanagerメソッドを追加する方法を見ていきます

Book modelにtitle_count()というメソッドを追加します(Book.objects.title_count()で使えるようになる)。このtitle_countメソッドはあるキーワードを含む本が何冊あるかを返すように定義します。

# models.py

from django.db import models

# ... Author and Publisher models here ...

class BookManager(models.Manager):
    def title_count(self, keyword):
        return self.filter(title__icontains=keyword).count()

class Book(models.Model):
    title = models.CharField(max_length=100)
    authors = models.ManyToManyField(Author)
    publisher = models.ForeignKey(Publisher)
    publication_date = models.DateField()
    num_pages = models.IntegerField(blank=True, null=True)
    objects = BookManager()

    def __str__(self):
        return self.title Here are some notes about the code:

self.filterのselfはManagerの事を指します。

>>> Book.objects.title_count('django')
4
>>> Book.objects.title_count('python')
18 

こんな感じになります。
よく実行されるクエリをカプセル化することによって同じコードを何度も書くことを防ぎます。

初期のmanagerのベースクエリセットを編集します

managerの基本のクエリセットはシステムの中のすべてのobjectを返します。例えばBook.objects.all() は全てのbookをデータベースから返します。このベースクエリセットはManger.get_queryset()をオーバーライドすることによってオーバーライドできます。get_queryset()は必ずクエリセットを返さなくてはなりません。

from django.db import models

# 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.

このモデルは二つのmanagerを持ちます。一つは普通のobjectsでもう一つはRoald Dahlの本だけ返すmanagerです。

Book.dahl_objects.all()
Book.dahl_objects.filter(title='Matilda')
Book.dahl_objects.count()

いろいろできます。

class MaleManager(models.Manager):
    def get_queryset(self):
        return super(MaleManager, self).get_queryset().filter(sex='M')

class FemaleManager(models.Manager):
    def get_queryset(self):
        return super(FemaleManager, self).get_queryset().filter(sex='F')

class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    sex = models.CharField(max_length=1, 
                           choices=(
                                    ('M', 'Male'),  
                                    ('F', 'Female')
                           )
                           )
    people = models.Manager()
    men = MaleManager()
    women = FemaleManager()

こうすると、
Person.people.all() すべての人を返す。
Person.men.all() すべての男性を返す。
Person.women.all() すべての女性を返す。

カスタムメソッドとmanegerの違い。
managerがテーブル級、カスタムメソッドは定義するとrow(行)レベルの機能をオブジェクトに加えます。