Django ForeignKeyのon_deleteキーについてまとめてみた

モデルに1対多の外部キー制約を設定できるForeignKeyにはon_deleteというキーワード引数があります。

on_deleteは参照先のデータが削除された時の動作を設定できます。

今回は、on_deleteに設定できるパラメーターを解説します。

on_deleteに設定できるパラメーター

ForeignKeyは以下の様に使います。on_deleteにmodels.SET_NULLを設定したパターンです。

user = models.ForeignKey(
    User,
    on_delete=models.SET_NULL,
    blank=True,
    null=True,
)

on_deleteにパラメーターを設定してもDBのSQL制約に影響はありません。

CASCADE

参照先が削除された場合、参照元のレコードも削除されます。

便利でよく利用されます。

SQL制約のON DELETE CASCADEと同じ挙動です。

削除されるオブジェクトのModel.delete()は実行されませんが、pre_deleteとpost_deleteシグナルは送られます。

PROTECT

参照先が削除される場合、ProtectedError例外を発生して参照先の削除を防ぎます 。

RESTRICT

Django3.1の新機能です。

参照先が削除される場合、RestrictedError例外を発生して参照先の削除を防ぎます 。

PROTECTと違い、参照先の削除が許可される事があります。

削除が許可される例は、公式ドキュメントを参照して下さい。

※公式ドキュメントの例は英語で理解に時間がかかったので、補足説明を書きます。
SongクラスのAlbumフィールドはmodels.RESTRICTが設定されています。

artist_twoを削除しようとすると、CASCADEの関係にあるalbum_twoも削除しようとしますが、album_twoはsong_twoとRESTRICTの関係にあるため削除できません。

artist_oneを削除する場合も、song_oneとalbum_oneがRESTRICTの関係がありますが、artistフィールドにartist_oneが設定されているため、削除が許可されます。

SET_NULL

参照先が削除された場合、nullを設定します。null=Trueである場合にのみ設定可能です。

便利でよく利用します。

NULLを避けたい場合は、以下のSET_DEFAULTやSET()が使えます。

SET_DEFAULT

参照先が削除された場合、デフォルト値を設定します。ただし、ForeignKeyにデフォルト値の設定が必要です。
次の例はデフォルト値にpk=1のレコードを指定しています。

user = models.ForeignKey(
    User,
    on_delete=models.SET_DEFAULT,
    default=1,
)

SET()

参照先が削除された場合、SET()に渡した値を設定します。また、SET()にcallable(呼び出し可能オブジェクト。関数など。)を渡した場合は、callableの結果を設定します。

models.pyのインポート時にクエリが実行されるのを避けるために、callableを渡す方法の方がよく使われます。

DO_NOTHING

参照先が削除されてもは何も実行しません。滅多に利用する事はないです。

データベースバックエンドが参照整合性を適用する場合、手動でデータベースのフィールドにON DELETE制約をつけない限り、IntegrityError例外が発生し得ます。

スポンサーリンク
スポンサーリンク