初期クエリを変更したくなる例マネージャーのカスタマイズよく使うfilter処理をマネージャーに定義するマネージャーとクエリセット概要Djangoでは、モデル名.objectsのようにすると様々なことができます。このobjectsはマネージャーと呼ばれるものです。このマネージャーは自分でカスタマイズすることもできます。カテゴリと記事のモデルがあり、カテゴリの一覧を表示する際に紐づいた記事数も一緒に表示したいとします。これはDjangoで、集計処理でも紹介したannotate()で実装することができます。次のようなモデルの例です。self.title例えば、カテゴリの一覧表示をするビューは次のようになるでしょう。queryset.annotate(post_count=Count('post')).order_by('-post_count')そして、category_list.htmlです。%}これは問題なく動きます。今のところ、ビューのget_queryset()を上書きするだけで済みます。この表示は便利なので、admin管理画面でもやりたくなるかもしれません。記事検索フォームでのカテゴリ欄でも同様に表示するとわかりやすいでしょう。なってくると、カテゴリを表示しそうな箇所全てを↑のようなコードにする必要があります。マネージャーのカスタマイズそこで、マネージャーのカスタマイズです。models.pyを編集します。self.nameCategoryのobjects属性を、CategoryManagerというものに変更しました。models.Manager()のようになっていて、Category.objects.all()のような処理をすると、マネージャークラスのget_queryset()が呼ばれます。今回のコードはそれを上書きしている形ですね。初期クエリの段階で記事数も一緒に返すようになったので、__str__()での表示名も一緒に変更しておくと捗るでしょう。self.nameすると、管理画面でも記事数がパッと確認できますね。使うfilter処理をマネージャーに定義する例えば記事に未来の日付を設定することができて、現在時間までの記事の一覧と、未来も含めたすべての記事一覧が欲しいかもしれません。filterでの絞り込みも勿論可能ですが、こういった場合、次のようなマネージャーを定義しておくと捗ります。self.titleこの例はget_queryset()を上書きしていません。その代わり、published()という独自のメソッドを定義しています。処理内容を見ればわかるように、これは現在時間までの記事だけ取得します。これにより、Post.objects.all()で全ての記事が取得でき、Post.objects.published()で公開記事だけを取得できるのです。ビュー等にfilter()で絞り込みをする必要はなくなり、直感的になりました。独自のメソッドは好きに追加できます。未来の記事だけを取得したいならば、次のようにできるでしょう。self.get_queryset().filter(created_at__gt=timezone.now())これは当然、Post.objects.private()で呼び出せます。マネージャーは複数利用できます。self.titleまず、記事にユーザーを紐付けてみました。objectsのほか、naritoというクラス属性にもマネージャーを指定しています。新しく作ったPostNaritoManagerは、get_querysetメソッドを上書きし、投稿者がnaritoの記事だけに絞り込みます。Post.narito.all()とすると、投稿者がnaritoの記事が予め取得される訳です。PostManagerのように、publishedのようなメソッドを定義することも、勿論可能です。好きにマネージャークラスを追加できるし、マネージャークラスにも、好きにメソッドを追加できます。get_querysetメソッドを上書きすれば、初期クエリも変更できました。ちなみにですが、ForeignKeyで逆側から一覧が欲しいときがありますね。ユーザ一覧を表示しながら、ユーザーが投稿した記事の一覧も表示したいケースです。テンプレートファイルで、次のように書くことになるでしょう。この投稿者の記事一覧を取り出すこの場合も、マネージャーのメソッドが呼び出せます。各ユーザーが投稿した、公開記事一覧とかも取れるわけですね。この投稿者の記事一覧を取り出すマネージャーとクエリセット一点注意なのは、今までのコードはあくまでマネージャークラスにメソッドを追加しています。クエリセットは、これらのメソッドを持っていません。マネージャークラスに次のようなメソッドが増えました。self.get_queryset().filter(人気な記事)popularメソッドです。これは、人気な記事を返します。公開されてて、人気な記事が欲しいならば、次のようなコードを書けそうですが...Post.objects.popular().published()残念ながら、このコードはエラーです。Post.objects.popular()で返されるのはクエリセットであって、マネージャークラスではありません。クエリセットには、publishedメソッドはありません。それがあるのは、あくまでマネージャーです。マネージャーと、クエリセットは別物なのです。self.get_queryset().filter(created_at__lte=timezone.now()).filter(人気な記事)人気ではない公開記事が欲しいときは、どうすればよいでしょう。似たようなメソッドを作るのでしょうか。それをするのも一つの解決策ですが、他の方法もあります。マネージャーと同様にクエリセットクラスも定義できるのです。self.titlePostQuerySetというクエリセットを作成しました。PostQuerySet.as_manager()としています。これは何かというと、クエリセットクラスを素にマネージャークラスを作るという意味です。これにより、Post.objects.published()は勿論動作しますし、Post.objects.published().popular()も動作します。マネージャーにもクエリセットにも同様のメソッドがあるので、呼び出せるという訳ですね。PostsDjangoで、集計処理Djangoで、データの平均値を求めたり、何個のデータが紐づくか、といった集計処理のサンプルを紹介しています。DjangoDjangoで、月別アーカイブ欄を作るDjangoで、ブログや日記によくある月別アーカイブ欄を作成していきます。DjangoDjango、日記のモデルを作るDjangoで、日記を作るシリーズの1つです。日記で使うモデルを作成していきます。DjangoComment記事にコメントするまだコメントはありません。幾つかの方法で、ブログの更新を受け取れます。