知識の枝

"All is well"

Django ForeignKeyを逆参照する方法

約186日前 2021年5月24日18:35
デジタル
Django HTML

改訂履歴


2021/5/24 投稿

1. 背景


Djangoを使った開発中に覚えたことを備忘録として残します。

今回は親モデルをForeignKeyで参照している子モデルをテンプレート内で逆参照する方法を解説します。


2. ゴール


ForeignKeyで参照されている側のモデルから、自身を参照しているモデルを逆参照する。
(ややこしい)


3. はじめに


言葉で書くとややこしくなったのでイメージで伝えます。



子モデルから自身の親モデルを参照する場合は
「子モデル.ForeignKeyのフィールド名」で可能ですよね。

2階層下からであれば、
「子モデル.ForeignKeyのフィールド名.ForeignKeyのフィールド名」で可能です。

では、親側から自分自身を参照している子モデルを逆参照する場合はどうするのでしょうか?
その方法を次項で解説します。


4. 逆参照


4.1 - related_name


まず1つ目の方法。

ForeignKeyフィールドに「related_name」を定義する。
このオプションを追加すると、ForeignKeyで指定された親要素から自身を参照している子モデルを逆参照できるようになります。

models.py
class Large(models.Model): #親のモデル
"""大項目"""

"""フィールド定義"""
title = models.CharField(verbose_name='大項目', max_length=50)


class Middle(models.Model):
"""中項目""" #子のモデル

"""フィールド定義"""
target_large = models.ForeignKey(Large, verbose_name='対象の大項目', on_delete=models.CASCADE, related_name='related_middle') #ここ
title = models.CharField(verbose_name='中項目', max_length=50)
中項目モデルのForeignKeyフィールドに「related_name」を追加しました。

あとはテンプレートで呼び出した大項目に対し、先ほど指定した「related_name」を「.relate_middle」という形で付けてあげればOKです。

html
{% for each_middle in large.related_middle.all %} #related_middleという参照ができるようになりました
{{ each_middle.title }}
{% endfor %}
これで親から子を逆参照できました。


4.2 - 子モデル名_set


2つ目の方法。

これは4.1項と異なり、モデルに変更を加える必要がありません。

テンプレートで呼び出した大項目に対し、「.子モデル名_set」を付けるだけです。

html
{% for each_middle in large.middle_set.all %} #middle_setという参照が可能です
{{ each_middle.title }}
{% for each_task in each_middle.task_set.all %} #子の子も参照可能です
{{ each_task.title }}
{% endfor %}
{% endfor %}
こちらのほうが手間が少なくて楽ですね。

逆参照方法は以上です。



5. さいごに


逆参照が使えると便利な場面が多いです。
ぜひ覚えましょう。お疲れ様でした。