投稿日:2019年11月11日
Djangoは簡単にWebアプリケーションを作成できるフレームワークです。この記事は初心者の方向けのDjangoチュートリアルです。
今回のチュートリアルの内容のModelMangerは開発していく中で必須のものではありません。
しかし、これを使いこなすことでコードは非常に完結に見やすくなります。
Djangoにおけるマネージャ (Manager) とは、Django のモデルに対するデータベースクエリの操作を提供するインターフェイスです。Django アプリケーション内の1つのモデルに対して、Manager は最低でも1つは存在します。
ModelのデフォルトのManger
前回いろんなQueryを実行してみる中でobjectsという変数を呼び出していました。
articles = Article.objects.all()
この様にModelクラスはdjango.db.models.Modelを継承した段階で、objectsというクエリを呼び出すManagerがついています。
継承しているので今見えていないですが、本当はArticleには下の様にobjectsという変数があります。
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
class Article(models.Model):
objects = models.Manager() # 見えていないが実際にはこれがある
[...]
QuerySetの呼び出しなどで見たobjectsはこれだったんですね!
ここで少し実際にブログのコードを作成する場面をイメージしてみましょう。ブログのトップページや、関連記事、人気記事ランキングや記事の詳細ページ、おそらくユーザーに見せる殆どのページは公開中(statusがpublished)の物になるでしょう。
このままだとコードを作成していく中で、大量にArticle.objects.filter(status="published")と書く事になります。これはコードの可読性的にも、コードを管理していく面から見ても得策ではないでしょう。
ここで新しいカスタムManagerを作成することでこの問題を解決してみましょう。
models.pyに新しくPublishedManagerを作成し、Articleモデルで設定してみます。
[...]
class PublishedManager(models.Manager):
"""
デフォルトで公開中のもののみを取得
"""
def get_queryset(self):
return super(PublishedManager, self).get_queryset().filter(status="published")
class Article(models.Model):
[...]
objects = models.Manager()
published = PublishedManager() # managerを追加
[...]
このPublishedManagerは公開中の物のみを取得するManagerです。これによってArticleモデルは次の様に公開中の記事を取得できます。
$ python manage.py shell
>>> from blog.models import Article
>>> Article.published.filter(author__username="marsquai")
<QuerySet [<Article: エンジニアの健康維持の秘訣とは?>, <Article: 君にもできるスクレイピング!>, <Article: Shellから変更された記事>, <Article: シェル記事>, <Article: 今夜の料理は?>]>
上の様にArticle.publishedでPublishManagerを呼び出した時、このManagerのget_queryset()メソッドが呼ばれます。このメソッドはQuerySetを返すメソッドです。
今回、このメソッドをオーバーライドして公開中のもののみのフィルタリングをしたことでデフォルトのフィルタがついたというわけですね!
なんとなく書いていたobjectsの意味が理解できたでしょうか?
コード中のfilter()で同じ条件のfilter()が増えた時には、カスタムのMangerを使うことを考えてみましょう。
わからなくなったら公式ドキュメントを参照しましょう。
公式ドキュメント:https://docs.djangoproject.com/ja/2.2/topics/db/managers/