Django2系以降のmodels.pyから必須になったon_deleteについて
Djangoでは、2.0以降のバージョンで、モデルを作成する際に、on_deleteというパラメータを指定することが必須になった。
on_deleteというのは、modelのForeignKeyで外部キーを作成する際に指定し、接続先のテーブルのレコードが削除された場合に、接続元のレコードをどうするのか(削除するのか残すのか)決めるパラメータである。
on_deleteを設定するには、models.pyの設定で以下のように記載する。
Example
- models.pyで、ForeignKeyを作成
class Model1(models.Model):
model2 = models.ForeignKey(Model2, on_delete=models.CASCADE) # CASCADEの場合には、外部レコードを削除した場合にレコードは自動削除される
date = models.DateField()
on_deleteのオプション一覧
- on_deleteオプション一覧と各意味
オプション | 意味 |
---|---|
CASCADE | ForeignKeyの対象レコードが削除されると、紐づけ元のレコードが全て削除される |
PROTECT | ForeignKeyの対象レコードが削除しようとしても、PrortectedErrorが発生して削除されない |
SET_NULL | ForeignKeyの対象レコードが削除されると、紐づけ元のレコードにはnullが設定される。またこれは、null=Trueと設定して利用しなければいけない |
SET_DEFAULT | ForeignKeyの対象レコードが削除されると、ForeignKeyにはデフォルト値が設定される。またこれは、モデルにdefault=を設定する必要がある |
SET() | SETの中に関数を設定すると、削除の際に設定した関数が呼び出される |
RESTRICT (Django3.1以降) |
参照先を削除する際にRestictedErrorを発生させて、保護する。ただし、参照先の参照先が削除される際に、CASCADEでその参照先に紐づけられいた場合には、保護されず削除される。 |
SET(), PROTECT, RESTRICTの具体的な利用方法
SET()とPROTECTとRESTRICTの仕組みはわかりにくいので、以下に具体例を上げてご説明する。
Example
- SET()の事例
from django.contrib.auth import get_user_model
from django.db import models
def get_sentinel_user():# 削除に実行される処理でreturnの値が削除されたレコードに設定される
return get_user_model().objects.get_or_create(username='deleted')[0]
class MyModel(models.Model):
user = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET(get_sentinel_user), # models.SETで削除時に実行される関数を設定する
)
RESTRICTとPROTECTは動作が似ているため、以下に図を用いて説明する。
- RESTRICTとPROTECTの違い
- RESTRICTの例
name = models.CharField(max_length=20)
school = models.ForeignKey( # RESTRICTを指定する。Schools削除時はエラー(RestictedError)
'Schools', on_delete=models.RESTRICT
)
prefecture = models.ForeignKey( # CASCADEを指定する。Schools削除時はSchoolsとともに該当レコード削除される
'Prefectures', on_delete=models.CASCADE
)
class Schools(models.Model):
name = models.CharField(max_length=20)
prefecture = models.ForeignKey( # CASCADEを指定する。Schools削除時は該当レコード削除される
'Prefectures', on_delete=models.CASCADE
)
class Prefectures(models.Model):
name = models.CharField(max_length=20)