見出し画像

Django_[prefetch_related]で外部参照データを指定する方法 #214日目

以前にご紹介したprefetch_relatedの追加情報です。

DBに何度もアクセスしてデータを取り出すの非効率なため、Djangoでは可能な限り少ないクエリでデータを取得するための「prefetch_related()」が用意されています。

これは指定したモデルに外部参照データがある場合に、1回のクエリで外部参照データ分まで取得してくれる機能を持っています(普通に取得すると指定したモデル&外部参照データで2回クエリが走る)。


今回はこの外部参照データにさらに外部参照データがあった場合に、同様に1回のクエリでデータを取得するための記述方法をご紹介します。

では早速見ていきます。


前提となるモデルは以下とします。CompanyモデルとMemberActionモデルが、MemberモデルにForeignKey (一対多) で紐づいています。

[aaa.py]
class Company(models.Model):
    member = models.ForeignKey('Member', on.delete=models.CASCADE, related_name='company')
    founding_date = models.DateField(verbose_name="創業日")

[bbb.py]
class Member(models.Model):
    name = models.CharField(max_length=255, blank=False)
    address = models.CharField(max_length=255, blank=False)

[ccc.py]
class MemberAction(models.Model):
    member = models.ForeignKey('Member', on.delete=models.CASCADE, related_name='actions')
    action = models.TextField(max_length=50, verbose_name="活動記録") 

この状態でCompanyモデル側から全てのデータを取得してみます。「'member'」はprefetch_related()の一般的な記述方法ですが、肝は「'member__actions'」です。

[Company_view.py]

from .models import Company

company =  Company.objects.prefetch_related('member', 'member__actions').filter(address="東京都").get()

つまり外部参照データ (member) の外部参照データ (actions)を表しています。

ここでややこしいのは、Memberモデルの中には直接的に「actions」が記述されておらず、MemberActionモデルを逆参照する形になっている点です。モデルが3つくらいなら簡単ですが、10個20個になってくると紐づきを把握するのが大変なので、注意が必要です。


ちなみにPythonでは等価を表すときは「==」ですが、上記の通りDjangoのfilterを使う際は「=」でOKです。


ここまでお読みいただきありがとうございました!


参考


この記事が気に入ったらサポートをしてみませんか?