Warning: count(): Parameter must be an array or an object that implements Countable in /home/xs638785/agile-software.site/public_html/wp-content/plugins/rich-table-of-content/functions.php on line 490
モデル同士を紐づけるときに、ForeignKey
やOneToOneField
を使いますが、その際、バージョン2からは引数としてon_delete
を指定することが必須となりました。
on_deleteとは、参照するオブジェクトが削除されたときに、それと紐づけられたオブジェクトも一緒に削除するのか、それともそのオブジェクトは残しておくのかを設定するものです。
on_deleteオプション | |
models.CASCADE | 一緒に削除される |
models.PROTECT | 削除できない |
models.SET_NULL | NULLがセットされる |
models.SET_DEFAULT | デフォルト値がセットされる |
models.SET | 任意の値がセットされる |
DO_NOTHING | 何もしない |
使用例
from django.db import models
class Author(models.Model):
"""作者"""
name = models.CharField(max_length=50)
def __str__(self):
return self.name
class Story(models.Model):
"""小説"""
author = models.ForeignKey(Author, on_delete=models.CASCADE)
title = models.CharField(max_length=50)
text = models.TextField()
def __str__(self):
return self.title
この設計によってこんなStorysテーブルができます。
例えばここでAuthorオブジェクト:”川端康成”を削除したときに、それと紐づいたStoryオブジェクト:”雪国”、”伊豆の踊り子”も削除するのか、それとも残しておくのかを設定するのがon_deleteです。
CASCADE
author = models.ForeignKey(Author, on_delete=models.CASCADE)
削除するオブジェクトに紐づいたオブジェクトを全て削除します。
例えば、以下の画像のようにAuthorオブジェクト”川端康成”を削除しようとして削除ボタンを押すと、
このように「関連付けられてるオブジェクトを削除します」とメッセージが出ます。
「はい」ボタンで、Authorオブジェクト”川端康成”が削除されるのと同時に、それに紐づいたStoryオブジェクトも全て削除されます。
PROTECT
author = models.ForeignKey(Author, on_delete=models.PROTECT)
関連付けられてるオブジェクトがあると、削除できません
この場合、Authorに紐づいたStoryがあるのでAuthorを削除することができません。関連付けられたStoryオブジェクトを全て削除すればAuthorも削除することができるようになります
SET_NULL
author = models.ForeignKey(
Author,
on_delete=models.SET_NULL,
null=True
)
オブジェクトが削除されると、代わりにNULLをセットします。
今回の例だと、Authorを削除するとStoryオブジェクトのauthorフィールドがNULL(空白)になります。
こんな感じで、Authorに誰も登録されていない状態になります。注意点として、authorフィールドはnull=Trueにしておく必要があります。
SET_DEFAULT
author = models.ForeignKey(
Author,
on_delete=models.SET_DEFAULT,
default=Author.objects.get(name="匿名")
)
削除されたオブジェクトの代わりに、デフォルト値が入るようになります。注意点として、authorフィールドにはデフォルト値を設定しておく必要があります。
このようにauthorフィールドにデフォルト値の”匿名”が入ります
SET()
自分で処理を自由に設定することができます。
今回は、”削除された著者”という文字列をauthorフィールドに入れる処理をします
def get_deleted_user():
return Author.objects.get_or_create(name="削除された作者")[0]
class Story(models.Model):
author = models.ForeignKey(Author, on_delete=models.SET(get_deleted_user))
title = models.CharField(max_length=50)
text = models.TextField()
DO_NOTHING
何の処理もしません。