0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Django Model~データ参照時のobjectsの正体~

Posted at

DBを参照したいデータに.objectsが必要なわけ

アプリケーション内で以下のようなモデルを作成しました.

models.py
class BaseMeta(models.Model):
  create_at  = models.DateTimeField(auto_now_add=True)#insert時に現在時刻を取得
  update_at  = models.DateTimeField(auto_now_add=True)#update時に現在時刻を取得

  class Meta:
    abstract = True#本クラスではDBにテーブルを作らない

class Person(BaseMeta):
  first_name = models.CharField(max_length=30)
  last_name = models.CharField(max_length=30)
  birthday = models.DateField(default=date(1990,1,1))
  email = models.EmailField(db_index=True)#index:検索高速化
  salary = models.FloatField(null=True)
  memo = models.TextField()
  web_site = models.URLField(null=True)

  class Meta:#オーバーライド
    db_table = 'person'#table名
    indexes = [models.Index(fields=['first_name','last_name'])]#複合インデックス
    ordering = ['salary']

  def __str__(self)
    return f"{self.pk}: {self.first_name}, {self.last_name}"

main.py
import os
os.environ.setdefault('DJANGO_SETTINGS_MODULE','ModelProject.settings')
from django import setup
setup()
from ModelApp.models import Person

#すべてのレコードを取得
persons = Person.objects.all()#←これ
for p in persons:
  print(p.pk, p.first_name,p.last_name)

ここの.objectsとは何?
と思い調べました.

結果

Django の モデルマネージャー(Manager) の仕組みによるためである.
つまり,Personはmodels.Modelを継承しているため、Djangoが自動的にそのクラスにobjectsというManagerのクラス変数として追加します。(インスタンス変数だと各インスタンスごとに異なるobjectsをもつため)
Django の Manager クラスは、django.db.models.Manager に定義されています。

以下のように解釈できます.

models.py
from django.db import models

class Person(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)

    # デフォルトの Manager (django.db.models.Manager) が自動で追加される
    # objects = models.Manager() が内部で行われる

このように,クラス継承によってPersonクラスは「自分自身」.objectsを経由してManagerのもつメソッドを使えるようになるわけです.

これによってできること

1. models.Modelにはobjectsという名前でManagerが自動的に定義されており、それがPersonクラスに「継承」という形で追加されます。
このobjectsを通じて、Personクラスに対するデータベースクエリができるようになります。
2. 自作メソッドを作れる(QuerySetを渡してあげる)
Managerはこのように定義されていて,
class Manager(BaseManager.from_queryset(QuerySet)):
pass
QuerySetをたとえばこのように渡します.

models.py
from django.db import models

class PersonQuerySet(models.QuerySet):
    def with_salary(self):
        return self.filter(salary__isnull=False)

# PersonQuerySet を持つ Manager を作成
PersonManager = models.Manager.from_queryset(PersonQuerySet)

class Person(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    salary = models.FloatField(null=True, blank=True)

    objects = PersonManager()  # カスタム Manager を適用

main.py
persons = Person.objects.with_salary()  # salary が NULL でないデータを取得

このように,自作でメソッド作成可能です.

まとめ

使いたいクラス(Person)にmodels.Modelを継承させることでPerson.objects.all()など簡単にデータ参照できる.
これは,Managerクラス(objects = models.Manager()が内部的に行われている)を継承し,データ操作用のobjects(=インターフェース?)を与えたため

解釈違いや発展があればご教示お願いたします

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?