課題
Railsにはscope
という機能があって、頻出のクエリに名前付けを行うことができます。
class Post < ActiveRecord::Base
scope :published, -> { where(published: true) }
end
Post.published
# SELECT "posts".* FROM "posts" WHERE "posts"."published" = 1
同じようなことをDjangoでもやりたいな、と思ってやり方を調べました。
解決方法
カスタマイズしたQuerySetと、ModelManagerを使うと、実現できるようです。
from django.db import models
class PostQuerySet(models.QuerySet):
def published(self):
return self.filter(published=True)
def latest(self):
return self.order_by('-updated_at')
class PostManager(models.Manager):
def get_queryset(self):
return PostQuerySet(self.model, using=self._db)
class Post(models.Model):
published = models.BooleanField()
# 他いろんなフィールド...
objects = PostManager() # custom managerを定義
使い方。
>>> Post.objects.all().published()
# SELECT "posts".* FROM "posts" WHERE "posts"."published" = 1
以下のようにチェーンさせることもできました。
>>> Post.objects.all().published().latest()
objects.all()
などをつかってQuerySet
を生成しないと使えないのがちょっと微妙な気もしますが、Viewなどが読みやすく実装できるようになると思います。