デフォルトマネージャについての補足

重要なところの説明が抜けていたので補足。

先にまとめ

get_query_setをオーバーライドしたマネージャを作ると地雷原になりうるので、オーバーライドしないor↑の対策を忘れないようにしましょう。

逆方向リレーションのことを考えると前者がおすすめです。

get_query_set

get_query_setは、そのManagerオブジェクトが最初に生成するQuerySetを返すメソッドです。

デフォルトだと対象モデルのすべてのオブジェクトを返す=なにもフィルタが掛かっていないQuerySetを返します。

これをオーバーライドすると、そのManager全体の挙動を変更できるので

class PublishedMyManager(models.Manager):
    def get_query_set(self):
        return super(PublishedMyManager, self).get_query_set().filter(is_deleted=False)

class DeletedMyManager(models.Manager):
    def get_query_set(self):
        return super(DeletedMyManager, self).get_query_set().filter(is_deleted=True)
                
class MyModel(models.Model):
    is_deleted = models.BooleanField(u"削除フラグ", default=False)
    user = models.ForeignKey(User, verbose_name=u"ユーザー")

    published = PublishedMyManager()
    unpublished = DeletedMyManager()

下らない例ですがこう定義すると

>>> MyModel.published.all()
[is_deleted=Falseのオブジェクトすべて]

>>> MyModel.unpublished.all()
[is_deleted=Trueのオブジェクトすべて]

という風に

  • 意味が分かりやすい
  • フィルタを通し忘れて削除されてるデータを表示してしまう危険性などが減る
  • フィルタ書くよりコードが短くなる

なコードが掛けていいことづくめ!

大域的な挙動を変えたい時はどんどんManager生やそうぜ!

と思っていました。

1つ目の記事にもどる

4/50