【django】モデルのリレーションフィールド:ForeignKey、OneToOneField、ManyToManyField
2021.06.13 /
本記事ではdjangoのモデルにおける、リレーションフィールド(ForeignKey、OneToOneField、ManyToManyField)について詳しく解説していきます。
djangoのデータベースで複数のモデルを扱う際、リレーションフィールドを用いてそれぞれのモデルを関係付けしていきます。
Webアプリケーション開発でデータベースを扱うことは必須です。
djangoでデータベースを操作するには、モデルmodelを使います。
Modelモデルの定義についての基本は、以下記事をご参照ください。
【Django】Model(モデル)とは:models.pyの書き方とデータベース連携(テーブル作成)
モデルを定義する際にフィールドを定義します。
フィールドの型やフィールドオプションについては、以下記事をご参照ください。
【django】モデルのフィールドについて:フィールドの型・オプション一覧
そのフィールド定義でリレーションフィールドという手法を使います。
ぜひ本記事でリレーションフィールドについて理解を深めてください。
リレーションフィールド
複数のモデル間(テーブル間)を紐づけるためにリレーションフィールドという手法を用います。
リレーションフィールドには次に示す3種類が用意されています。
リレーションフィールド | 関係性 |
---|---|
ForeignKey | 多対一 |
OneToOneField | 一対一 |
ManyToManyField | 多対多 |
ForeignKey:外部キー
リレーションフィールドForeignKeyは、他モデルと多対一のリレーションを持つフィールドを作成します。
ForeignKeyを用いることで、そのフィールドのモデルを別モデル(テーブル)と紐づけます。
つまり「多対一」の関係を持つ2つの異なるモデルを結びつけるためにForeignKeyでフィールドを作成するということです。
ForeignKey(to, on_delete, **options)
ForeignKeyには2つの引数(to, on_delete)を必ず指定する必要があります。
toには紐づけるモデルを指定し、on_deleteには親フィールドが削除されたときの動作を指定します。
「1」になるモデルが親、「多」になるモデルが子の関係となります。
ForeignKeyのフィールドは子側に作成します。
例としては、Departmentという部署モデルとPersonという人モデルがあった場合、Departmentが「1」、Personが「多」となります。
なぜなら、1つの部署には多くの人が属しており、1人の人は1つの部署に属しているからです。
これを図で表すと次のようになります。
その他にもブログの投稿者(一)とブログ記事(多)の関係や、学校のクラブ(一)と生徒(多)の関係などがあります。
models.py
DepartmentとPersonの各モデルがmodels.pyでは、次のようになります。
from django.db import models
class Department(models.Model):
department_name = models.CharField(max_length=255)
def __str__(self):
return self.department_name
class Person(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
department = models.ForeignKey(Department, on_delete=models.CASCADE)
関連先のモデルを参照する
ForeignKeyによって関連を持ったモデル間で相手モデルのフィールドを参照することができます。
例えばUserモデル(ForeginKey:department)からDepartmentモデル(親)を参照するには次のように記述します。
>>> obj = User.objects.get(id=1)
>>> obj.department
ForeignKeyのフィールドが定義されていない側のモデルから、ForeignKeyが定義されているモデルを参照(逆参照)する方法については以下記事をご参照ください。
【Django】ForeignKey:一側から多側のモデルを参照(逆参照)する方法(_set)
OneToOne
リレーションフィールドOneToOneは、他モデルと一対一のリレーションを持つフィールドを作成します。
OneToOneを用いることで、そのフィールドのモデルを別モデル(テーブル)と紐づけます。
つまり「一対一」の関係を持つ2つの異なるモデルを結びつけるためにOneToOneでフィールドを作成するということです。
OneToOneField(to, on_delete, parent_link=False, **options)
OneToOneFieldはForeignKeyにオプションunique=Trueにしたようなフィールドです。
例としてはショッピングサイトで、利用者UserモデルとショッピングカートCartモデルが一対一の関係となります。
models.py
UserとCartの各モデルがmodels.pyでは、次のようになります。
from django.db import models
class User(models.Model):
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
def __str__(self):
return self.first_name
class Cart(models.Model):
user = models.OneToOneField(User, related_name=”user_cart”)
ManyToMany
リレーションフィールドManyToManyは、他モデルと多対多のリレーションを持つフィールドを作成します。
ManyToManyを用いることで、そのフィールドのモデルを別モデル(テーブル)と紐づけます。
つまり「多対多」の関係を持つ2つの異なるモデルを結びつけるためにManyToManyでフィールドを作成するということです。
例としては、Personモデルと趣味を保持するHobbyモデルが多対多の関係となります。
一人が複数の趣味を持つこともありますし、一つの趣味が複数の人に持たれているので多対多となります。
models.py
PersonとHobbyの各モデルがmodels.pyでは、次のようになります。
from django.db import models
class Hobby(models.Model):
hobby_name = models.CharField(max_length=255)
class Person(models.Model):
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
hobbys = models.ManyToMany(Hobby, blank=True)
def __str__(self):
return self.first_name
フィールドオプション
on_deleteオプション(OneToOneField、ForeignKey)
フィールドオプションon_deleteによって、紐づいている親フィールドのレコードが削除された場合の、子フィールドの動作を指定できます。
on_deleteが使えるフィールドの型はForeignKeyとOneToOneFieldのみです。
on_deleteで指定できる値は次のようになります。
on_delete | 意味 |
---|---|
models.CASCADE | 親データが削除されると結びついている子データも削除される |
models.PROTECT | 結びついている子データがある場合は親データを削除できない |
models.SET_NULL | 親データが削除されると子データにNullをセットする |
models.SET_DEFAULT | 親データが削除されると子データにデフォルト値をセットする |
models.DO_NOTHING | 親データが削除されても何もしません |
related_nameオプション
related_nameオプションは、指定した名前で逆参照(1側のモデルから多側のモデルを参照)できるようにしたい場合に使用します。
to_field
紐づけるモデルのフィールドを指定できます。
category = models.ForeignKey(‘Category’, to_field=’category_id’, on_delete=models.SET_NULL, null=True)
まとめ
本記事「【django】モデルのリレーションフィールド:ForeignKey、OneToOneField、ManyToManyField」はいかがでしたか。
Webアプリケーションで複数のモデル(テーブル)を扱う場合、リレーションフィールドはほぼ必須の知識です。
中規模または大規模なシステムの開発ができるように、モデル・モデルの型・オプション・リレーションフィールドを本サイトを通してマスターしてください。