りきゅーの技術メモ

SFC18。東京に魂を売った関西人。コンピュータサイエンス、ドローン、お茶、弓道、哲学とか。スケボーかスノボー始めたい。

【Django】on_deleteは何をするのか。

何ついて話す?

 DjangoでRESTfulなAPIを開発中です。そんな中models.pyでのモデル記述において、ForeignKeyフィールドを使う際には必ずon_delate引数をしていなければいけません。デフォルトではCASCADEになっているので何となくそのままCASCADEにしがちですが、ちゃんとコイツの意味を知らない思い通りのデータベースを構築できないと気づいたので話します。

on_delate

 on_deleteは例えばmodels.pyの以下のような場面で登場します。

class UserLike(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    artist = models.CharField(max_length=16)

 userフィールドはUserスキーマとのリレーションフィールドになっています。そしてon_deleteが指定されています。
 on_deleteとはリレーションとして繋がっている先(つまりUserスキーマ側)のユーザーデータが削除された時に、UserLikeスキーマ側のデータをどうするかの挙動を示す引数なのです。
 この値にはいくつかの種類があります。いくつか基本的なものを紹介します。

CASCADE

 CASCADEはリレーション先のデータが削除されると、こちら側のデータも一緒に削除されることを意味します。

SET_NULL

 SET_NULLはリレーション先のデータが削除されると、こちら側のデータは残り、リレーションとして紐づいていたフィールドだけがNULL値になります。例えば以下の例では、、、

class MatchingLog(models.Model):
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True)
    teacher = models.ForeignKey(Stylist, on_delete=models.CASCADE)
    datetime = models.DateTimeField()
    rate = models.ImageField(blank=True, choices=RATE_CHOICES)

 これはユーザーと家庭教師のマッチングアプリのモデル(?)ですが、例えばユーザーのデータが退会などで削除されても、家庭教師のレイティングは削除されて欲しくないのでon_deleteをSET_NULLにして置くことで、ユーザーの値はNULLになってデータは残ります。こういう時に使えます。
 ちなみにSET_NULLに設定するにはnull=Trueという引数も指定し、そのフィールドでNULL値を使うことを許可しなくてはいけないです。

PROTECT

 PROTECTを指定すると、リレーションとして紐づいているデータがあれば削除ができないようにできます。例えば上記の家庭教師マッチングアプリの場合、一度マッチングをし、MatchingLogスキーマ側から参照されたユーザーデータは削除ができなくなります。一度もマッチングをせず、MatchingLogスキーマ側のデータと全く紐づいていないユーザーデータは削除できます。

SET_DEFAULT

 SET_DEFAULTはリレーション先のデータが削除されると、default引数に指定しておいた値が削除されたデータの代わりに入るようになっています。

class Food(models.Model):
   name = models.CharField(max_length=16)
   category = models.ForeignKey(Category, on_delete=models.SET_DEFAULT,
                                default=Category.objects.get(name='中華'))

 上記の例の場合、例えば’和食’というカテゴリーが削除されれば、そこに紐づけられていた食品はずべてデフォルトに設定していた'中華'のカテゴリーになります。めちゃくちゃですが.....

参考記事

Djangoon_deleteを使う(django2.0から必須)
narito.ninja