📑

DjangoでCustom Managerを利用して、Railsのfind_by風オブジェクト取得を実現する

2023/02/06に公開

書くこと

利用する技術

  • Django
  • model.Manager

今日のゴール

このようなArticleモデルが定義されていたとき

class Article(models.Model):
    title = models.CharField(max_length=100)
    # (省略)
    is_active = models.BooleanField(default=True)

呼び出し側では、以下のようにオブジェクトの取得ができる。

# 期待する取得結果: 
# Article<(1)> or None
article = Article.get_object_or_none(pk=1)

# 複数ある検索条件の場合:
# MultipleObjectsReturned
article = Article.get_object_or_none(is_active=True)

方法論

CustomManagerを定義

model/manager/base_manager.py

from django.db import models


class BaseManager(models.Manager):
    def get_object_or_none(self, **kwargs):
        try:
            return self.get_queryset().get(**kwargs)
        except self.model.DoesNotExist:
            return None

ここの処理では意図的に MultipleObjectsReturnedを握りつぶしていません。

Railsのfind_byでは複数件ある場合には1件目を取得するため挙動が異なります。

model/manager/base_manager.py

from .managers.base_manager import BaseManager

class ArticleManager(models.BaseManager)
    pass

Articleモデルで利用する

models/article.py

from .managers.article_manager import ArticleManager


class Article(models.Model):
    # (前略)
    objects = ArticleManager()

参考

Discussion