外部キー(on_delete=models.CASCADE)について調べたらStackOverflowの回答が素敵だった

何かと思ったので調べたら、Stackoverflowで良さげな回答を見つけた。

今回わかんないのはこれ

on_delete=models.CASCADE

Djangoのモデルで外部キーを使うときに一緒に併記してあるのを何度か見かけた。なんとな〜〜く意味は推測できるけど、ちゃんと理解しようということで調べてみた。そしたらStackoverflowで良い解説を見かけたので翻訳して置いておきます。

stackoverflow.com

タイトル「Djangoon_delete doって何の処理をしてるの?」

質問

僕はDjangoをよく使うんだけど、modelsのオプションにon_delete=models.CASCADEっていうのがあるのに気がついたんだ。ドキュメントで調べたんだけどこんなことしか書いてなくて。

Changed in Django 1.9:

on_delete can now be used as the second positional argument (previously it was typically only passed as a keyword argument). It will be a required argument in Django 2.0.

用例:

  • on_deleteはどんな処理をしてるの?(モデルが削除されたときに実行されるものだとは思うんだけど)
  • models.CASCADEは?(これについてはドキュメントには全く載ってなかった)
  • ほかにどんなオプションがあるのかな?(たぶんあるよね)
  • ドキュメントのどこにこれについて書いてあるか知ってる?

一番高評価が多い回答

これは外部キーで参照してるオブジェクトが削除されたとき、その削除に合わせて行われる処理についての記述なんだ。オプションは6つあるよ。この処理はDjango特有のものじゃなくて、SQLの標準的な機能なんだ。

  • CASCADE: 参照しているオブジェクトが削除されたら一緒に削除する(たとえば、ブログの記事を消したらそこに寄せられたコメントも必要ないよね) SQLCASCADEと同じ。
  • PROTECT: これはオブジェクトが削除されるときも、参照されたオブジェクトは削除しない。もし全てのオブジェクトを削除したいなら全部手動でやらなきゃならない。SQLのRESTRICTと同じ。
  • SET_NULL: これはオブジェクトが削除された時、参照先にNULLを代入する。(だから参照先はNullableにしておく必要がある) たとえば、ユーザを削除するとき、ユーザが寄せたコメントだけは匿名で残したいときなんかはこれが使える。SQLのSET NULLと同じ。
  • SET_DEFAULT: オブジェクトが削除されたとき、デフォルトの値を代入する。SQLのSET DEFAULTと同じ。
  • SET(...): 設定した値を代入するやつ。これはSQLにはない機能で、Django独自のやつ。
  • DO_NOTHING: たぶん、これは使うべきじゃない。何かしらの問題が君のデータベースで生じるだろう。(存在しないオブジェクトを参照する。とかね) SQLのNO ACTIONと同じ。

情報元: Model field reference | Django documentation | Django

こっちも参照してみて。PostgreSQL: Documentation: 10: CREATE TABLE

だいたいの場合は、CASCADEが想定される動作だ。だけどそれぞれの外部キーごとに、常に状況に応じた処理を考えるべきだ。PROTECTとSET NULLはよく使うし便利だよ。もしCASCADEを設定すべきでないところに設定しちゃったら、場合によっては一人のユーザ情報を削除するだけでデータベースのすべてのデータが消えることもあるからね。

まとめ

抽象から具体、アドバイスまである素晴らしい回答ですねぇ。ただレファレンスをバーン!とかコードバーン!みたいな回答と質が違う。こういうアドバイスができる人になりたいものです。

この回答をみて反省するところがありました。なんとな〜〜くサンプルからとってきたまま、CASCADEにしたりしてたことがあったけど意外と危険なことでした。ちゃんと学ぶって大事ですね。SQL周りの知識がまだ全然ないなぁと反省。データベースに強くなりたいものです。どこでもデータベースはあるからね!!!