Django Adminサイトの一覧画面で見えない = レコードが無い訳では無い。
「あれ?レコードが無いから削除されているはずだよな・・・?」と勘違いしていたので再現方法を書く。
モデルを用意する
例として、所属部署と社員のテーブルを作成する。
社員側のテーブルのon_delete
とdb_constraint
の設定値がポイント。
from django.db import models class Department(models.Model): """所属部署""" name = models.CharField("名前", max_length=100) def __str__(self): return self.name class Employee(models.Model): """社員""" name = models.CharField("名前", max_length=100) department = models.ForeignKey( Department, on_delete=models.DO_NOTHING, db_constraint=False, ) def __str__(self): return self.name
レコードを登録する
そして、適当なレコードを登録する。
と登録した。名前は単純に自分が直近再生していたアーティストの名前である。
部署を削除する
部署の商品企画部
を削除する。
この時は今回の設定値だと、以下のような挙動になる。
on_delete=models.DO_NOTHING
- なので
nibu
のレコードは削除されない https://docs.djangoproject.com/ja/5.0/ref/models/fields/#django.db.models.DO_NOTHING
db_constraint=False
- なので外部キーに対しての制約も無く、削除出来る(
True
の場合はon_delete=models.DO_NOTHING
の制約もあり、IntegrityError
が発生して削除できない) - https://docs.djangoproject.com/ja/5.0/ref/models/fields/#django.db.models.ForeignKey.db_constraint
一覧画面を見る
Employeesの一覧画面を見ると、さっきまで表示されていた
- 商品企画部: nibu
が無くなっている。
しかし、よく見ると 画面の左下には 4 employees
と記載されている。
そのためURLを直接操作して開くと、レコードがある事が確認できる。
ちなみに、Django Admin画面上からはdepartmentカラムの値が無さそうに見えるが、実際には4
の値が入っている。
sqlite> SELECT * from company_employee; 1|KIRINJI|1 2|マカロニえんぴつ|2 3|平井堅|3 4|nibu|4
以上より、Django Adminサイト上から「ぱっと見」無かったとしてもレコードが削除されたとは言い切れない事がわかる。
ちゃんとDBを見て、レコードを確認する必要がある。
余談
今回のようなケースだと、on_delete=CASCADE
を利用したり、そもそもデフォルトの設定値であるdb_constraint=True
を利用することが多いと思っている(ここは正直まだあまり詳しくない)。
db_constraint
については公式リファレンスにもデフォルトはTrue
が望ましいと書かれている。
デフォルトは True で、ほとんどの場合それが望ましい設定です。
また、続けて有効なケースとして以下の例が挙げられている。
無効なレガシーデータを持っている場合。 データベースをシャーディング(分割)している場合。
自分としては記録系のその時に起こった内容を正確に記録する必要がある
テーブルだと、こういう設定をする必要があると個人的には考えている。データベース設計は難しい。