【Django】ForeignKeyの引数で指定するrelated_nameについて

時計 2022.03.21 / 時計

【Django】ForeignKeyの引数で指定するrelated_nameについて

本記事ではDjangoにおける、ForeignKeyの引数で指定できるrelated_nameについて解説してきます。

Djangoの解説サイトではForeignKeyのオプションにrelated_nameを指定していたり、指定していないフィールドがあって、どんな役割を果たしているのかわからないですよね。

related_nameは使用方法を理解するとWebアプリケーションの作成にとても役立ちます。本記事を通してぜひrelated_nameの知識を深めてください。

models.py:リレーションフィールド

リレーションフィールドとは

Djangoで利用するリレーショナルデータベースでは3つのリレーション(「一対一」、「多対一」、「多対多」)があります。

これらリレーション(関連)は以下のリレーションフィールドで定義できます。

リレーションフィールド 関係性
ForeignKey 多対一
OneToOneField 一対一
ManyToManyField 多対多

リレーションフィールドは関連があるモデル間(テーブル間)を紐づけるために使用するということです。

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

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

リレーションフィールドの一つ、ForeignKeyは「多対一」の関連を持つモデル同士を関連付け(結び付け)ます。

ForeignKeyで関係付けられたモデルオブジェクト間で、関連モデルのフィールドを参照することができます。親(一側)から子(多側)のモデルを参照することを逆参照と呼びます。

ForeignKeyのフィールドが定義されていない側のモデルから、ForeignKeyが定義されているモデルを参照(逆参照)する方法は以下記事をご参照ください。

ここで解説した逆参照は次項より解説するrelated_nameに大きく関係します。

ForeginKey:related_name

related_nameとは

models.pyでForeignKeyを指定する場合、以下の構文で記入します。

構文

ForeignKey(to, on_delete, **options)

ForeignKeyには2つの引数(to, on_delete)を必ず指定する必要があります。toには紐づけるモデルを指定し、on_deleteには親フィールドが削除されたときの動作を指定します。

そしてrelated_nameはForeignKeyに指定できるオプションの一つです。オプションなのでrelated_nameは指定しなくても大丈夫です。

related_nameを指定することにより、逆参照する際にrelated_nameで指定した値で逆参照ができるようになります。

つまりrelated_nameを指定すると、<関連先モデルのクラス_set>ではなく、related_nameで指定した値で逆参照を行うということです。

related_nameの使用例

related_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

上記モデルでDepartment(親)からUser(子)を_setによる逆参照する場合、次のように記述します。

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

それでは次にrelated_nameを以下のようにForeignKeyに指定します。

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

このようにForeignKeyのオプションにrelated_nameを指定すると逆参照は以下のように記述できます。

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

このようにrelated_nameを使うことにより、コードのわかりやすさ・理解のしやすさが格段によくなります。

必ずrelated_nameを使用する場面

基本的にはForeignKeyのオプションにrelated_nameは指定しなくてもいいのですが、必ず指定しなければならない場面があります。

それは一つのモデルクラスで複数のフィールドにForeignKeyを使うときです。

例えば以下のようなモデルを考えてみましょう。

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)
    previous_department = models.ForeignKey(Department, on_delete=models.CASCADE)
    def __str__(self):
        return self.username

Userでは2つのフィールドでForeignKeyを使っています。実はこのモデルではエラーが発生してしまいます。

なぜならこれでは逆参照ができないからです。
obj.user_setではdepartmentとprevious_departmentのどちらを指定しているのかわからないですよね。

このように2つのフィールドでForeignKeyを使った場合は次のようにrelated_nameを指定する必要があります。

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

まとめ

本記事「【Django】ForeignKeyで指定するrelated_nameについて」はいかがでしたか。

related_nameの特徴を以下にまとめます。

  • 逆参照する際にrelated_nameで指定した値で逆参照ができるようになる
  • ForeignKeyのオプションの一つ
  • ForeignKeyに指定しなくても良い
  • 指定することで<関連先モデルのクラス_set>に代わって逆参照で使用できる
  • 見た目で直感的にわかるようになる
  • 一つのモデルクラスで複数のフィールドにForeignKeyを使う場合はrelated_nameを必ず指定する

上記の特徴を覚えて、related_nameを使ってみてください。