はじめに
この記事は、Django Advent Calendar 2018 21日目の記事です。
話すこと
全然たいしたことじゃないですけどtipsとして、最近気に入ってるカスタムManagerの書き方を紹介します。
Manager.from_queryset
「Managerで定義したメソッドをQuerySetとしても使いたい(逆のパターンも然り)」といったユースケースけっこうあると思います。そんなときに、Manager.from_queryset
を使ってManagerを生成するとシンプルに実装できておすすめです。
公式ドキュメント: https://docs.djangoproject.com/en/2.1/topics/db/managers/#from-queryset
you might want both a custom Manager and a custom QuerySet. You can do that by calling Manager.from_queryset() which returns a subclass of your base Manager with a copy of the custom QuerySet methods:
Manager.from_queryset
を呼び出すことで、カスタムQuerySetのメソッドを備えているManagerのサブクラスを取得できるよって書いてます。
実際にコードに落とし込んで見てみましょう。
class Todo(models.Model):
name = models.CharField(max_length=100)
description = models.TextField(blank=True, default='')
assignee = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, on_delete=models.SET_NULL)
start = models.DateField(null=True, blank=True)
end = models.DateField(null=True, blank=True)
is_active = models.BooleanField(default=True)
このようなTodoモデルを用意します。ここでアクティブなTodoだけ(is_active=True
)を取得したいという要望がでてきたとしましょう。さっそくManager.from_queryset
を使って追加実装してみます。
class TodoQuerySet(models.QuerySet):
def filter_active(self):
return self.filter(is_active=True)
class TodoQueryManager(
models.Manager.from_queryset(TodoQuerySet)):
pass
class Todo(models.Model):
objects = TodoQueryManager()
name = models.CharField(max_length=100)
description = models.TextField(blank=True, default='')
assignee = models.ForeignKey(settings.AUTH_USER_MODEL, related_name='todos', blank=True, null=True, on_delete=models.SET_NULL)
start = models.DateField(null=True, blank=True)
end = models.DateField(null=True, blank=True)
is_active = models.BooleanField(default=True)
これで以下のようにManager, QuerySet両方で、アクティブなTodoを取得するfilter_active()
メソッドを使うことができるようになります。
Todo.objects.filter_active()
user.todos.filter_active()
同じ実装を2回しないで済むので、シンプルでいいですね。
終わりに
このやり方は、TakesxiSximadaに教えてもらいました 。ありがとうございます
それでは メリークリスマス