LoginSignup
11
2

More than 3 years have passed since last update.

Django ForeignKeyのon_deleteの引数

Last updated at Posted at 2020-10-21

参考

Django 公式
stackoverflow

ForeignKeyのon_deleteの動き

on_deleteは参照元オブジェクトが削除された時に、
そのオブジェクトを削除するのか残しておくのかを決めておきます!!

models.py
# サンプルのモデル
class Book(AbstractModel):
    publisher = models.ForeignKey(Publisher, on_delete=models.CASCADE)

models.CASCADE

参照しているオブジェクト(例: Publisher)が削除されたら
一緒にオブジェクト(例: Book)を削除する
例: ブログの記事を消したらそこに寄せられたコメントも必要ないから消す

models.PROTECT

参照しているオブジェクト(例: Publisher)が削除されても
オブジェクト(例: Book)は削除しない
全てのオブジェクトを削除したいなら全部手動でやらなきゃならない。

models.SET_NULL

参照しているオブジェクト(例: Publisher)が削除されたら
オブジェクト(例: Book)にはNULL(例: establishmentにNULL)がセットされる
例: ユーザを削除するとき、ブログにユーザが寄せたコメントだけは匿名で残したいときなんかはこれが使える。
※null=Trueにする必要あり。

models.SET_DEFAULT

参照しているオブジェクト(例: Publisher)が削除されたら
オブジェクト(例: Book)にはdefaultで設定した値(例: establishmentにdefault)がセットされる

models.py
publisher = models.ForeignKey(Publisher, on_delete=models.SET_DEFAULT, default='不明')

models.SET

独自で設定した値を代入する。
callableを渡す。

models.py
def get_publisher():
    # とりあえず一つ目返す
    return Publisher.objects.all().first()

class Book(AbstractModel):

    publisher = models.ForeignKey(Publisher, on_delete=models.SET(get_publisher))

models.RESTRICT

※これはDjango3.1の機能です。
オブジェクトを削除する際に
参照しているオブジェクトが存在すると、削除せずにRestrictedErrorとする。

models.py
class Artist(models.Model):
    name = models.CharField(max_length=10)

class Album(models.Model):
    artist = models.ForeignKey(Artist, on_delete=models.CASCADE)

class Song(models.Model):
    artist = models.ForeignKey(Artist, on_delete=models.CASCADE)
    album = models.ForeignKey(Album, on_delete=models.RESTRICT)
console
artist_one = Artist.objects.create(name='artist one')
album_one = Album.objects.create(artist=artist_one)
song_one = Song.objects.create(artist=artist_one, album=album_one)
album_one.delete()
# Raises RestrictedError.
# 参照しているsongが存在するためエラー


artist_two = Artist.objects.create(name='artist two')
album_two = Album.objects.create(artist=artist_two)
song_two = Song.objects.create(artist=artist_one, album=album_two)
# artist_oneを使っていることに注意
artist_two.delete()
# Raises RestrictedError.
# artist_twoを削除するとCASCADEしているalbumも削除されるため、
# 参照しているSongでエラーが発生する
11
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
2