【Django】ForeignKey:一側から多側のモデルを参照(逆参照)する方法(_set)

時計 2022.03.20 / 時計

【Django】ForeignKey:一側から多側のモデルを参照(逆参照)する方法(_set)

本記事ではDjangoにおける、ForeignKeyで多対一の関係にあるモデル間で、一側のモデルから多側のモデルを参照(逆参照)する方法について解説していきます。

Djangoで複数の関係するモデルを利用する場合、リレーションフィールド(ForeignKey、OneToOneField、ManyToManyField)を用いて各モデル間を関係付けします。

リレーションフィールドのForeignKeyで関係付けられたモデル間で、親(一側)から子(多側)のモデルを参照し、各フィールドの値を取得したいことがあります。

本記事を通してForeignKeyのフィールドが定義されていない側のモデルから、ForeignKeyが定義されているモデルを参照(逆参照)する方法を学びましょう。

リレーションフィールド:ForeignKey

ForeignKeyとは

リレーションフィールドの一つ、ForeignKeyは「多対一」の関係があるモデル間を関連付けます。「1」側が親、「多」側が子となる関係になります。

主にForeignKeyフィールドは多側のモデルクラスに設けます。

リレーションフィールドについて詳しくは以下記事をご参照ください。

多側から一側のモデルを参照する

多側(子)から一側(親)のモデルを参照する方法を解説していきます。

例えばUserモデル(ForeginKey:department)からDepartmentモデル(親)を参照するには次のように記述します。

>>> obj = User.objects.get(id=1)
>>> obj.department

上記ではUserモデルからget(id=1)でUserオブジェクトを生成し、「department」フィールドからDepartmentモデルを参照しています。

Departmentモデルがnameフィールドを持っていた場合、次のようにして値を取得できます。

>>> obj = User.objects.get(id=1)
>>> obj.department.name

一側から多側のモデルを参照(逆参照)する方法

サンプルモデル

ここからの解説には以下サンプルモデルを使って解説を進めていきます。

class Dapartment(models.Model):
    name = models.CharField(max_length=255)
    address = models.CharField(max_length=255)
    def __str__(self):
        return self.name

class User(models.Model):
    username = models.CharField(max_length=100, unique=True)
    department = models.ForeignKey(Department, on_delete=models.CASCADE)
    def __str__(self):
        return self.username

models.pyにモデルを定義するする基本については以下記事をご参照ください。

models.pyのクラスで指定するフィールドの型やフィールドオプションについては以下記事をご参照ください。

一側から多側のモデルを参照(逆参照)

一側(親)のモデルから多側(子)のモデルを参照(逆参照)する方法について解説していきます。

逆参照で多側のモデルオブジェクトを取得するには_set属性名を利用します。

構文

関連先モデルのクラス_set

上記構文の注意点として、関連先のモデルクラス名は小文字で記述することです。
models.pyでは先頭大文字ですが、逆参照では必ず小文字にします。

例としてサンプルモデルを使って逆参照するコードを以下に記します。

>>> obj = Department.objects.get(id=1)
>>> for user in obj.user_set.all():
...    print(user.username)

上記コードではまずDepartmentでid=1のクラスオブジェクトを生成しています。
2行目では_setを使ってDepartmentからUserを逆参照しています。

このようにしてForeignKeyが定義されていないモデル側から、定義されているモデルを参照します。

ここで使用した_setは多対多のリレーション(ManyToManyField)でも同じように利用することができます。

テンプレートで逆参照

テンプレートで逆参照を行う場合は、タグや変数表示を用いて以下のように記述できます。

{% for user in obj.user_set.all %}
    <p>{{ user.username }}</p>

上記のようにテンプレートで記述することで、テンプレートでも問題なく逆参照を行うことができます。

まとめ

本記事「【Django】ForeignKey:一側から多側のモデルを参照(逆参照)する方法(_set)」はいかがでしたか。

Djangoでデータベースを扱う際、逆参照はよく利用する技術です。ぜひご自身のWebアプリケーションでも利用してみてください。