前々回はSELECT、前回はINSERT, UPDATEだったので、今回はDELETEを書いてみます。
なお、ベースのアプリは前回のものを引き継ぎます。
環境
DELETE
全件削除
Deletion.objects.all().delete() #=> DELETE FROM "runner_deletion"
条件に一致したレコードのみ削除
Deletion.objects.filter(name='foo').delete() #=> 'DELETE FROM "runner_deletion" WHERE "runner_deletion"."name" = %s' - PARAMS = ('foo',)
ON DELETE時の挙動
ModelのForeignKeyでon_delete
設定時の挙動が気になったため、各パターンを試してみました。
- Model field reference - #django.db.models.ForeignKey.on_delete | Django documentation | Django
- DjangoのQuerySet.delete が発行するクエリ - Qiita
Modelの用意
親Model(xxxKey)と、それを外部キー指定した子Model(Deletion)を用意します。
また、on_delete
パターン数分、子Modelでmodels.ForeignKey()
列を用意します。
Model field reference - #django.db.models.ForeignKey.on_delete | Django documentation | Django
class CascadeKey(models.Model): name = models.CharField(max_length=100) class ProtectKey(models.Model): name = models.CharField(max_length=100) class SetNullKey(models.Model): name = models.CharField(max_length=100) class SetDefaultKey(models.Model): name = models.CharField(max_length=100) class SetKey(models.Model): name = models.CharField(max_length=100) class DoNothingKey(models.Model): name = models.CharField(max_length=100) class Deletion(models.Model): name = models.CharField(max_length=200) cascade_row = models.ForeignKey(CascadeKey, on_delete=models.CASCADE) protect_row = models.ForeignKey(ProtectKey, on_delete=models.PROTECT) set_null_row = models.ForeignKey(SetNullKey, null=True, on_delete=models.SET_NULL) set_default_row = models.ForeignKey(SetDefaultKey, default=9, on_delete=models.SET_DEFAULT) set_key_row = models.ForeignKey(SetKey, default=10, on_delete=models.SET(11)) do_nothing_row = models.ForeignKey(DoNothingKey, on_delete=models.DO_NOTHING)
DELETEの実行
CASCADE
# 事前データ #=> Deletion_model: [{'cascade_row_id': 3, 'name': 'foo', 'id': 5}] *関係する部分のみ CascadeKey.objects.all().delete() #=> Deletion_model: []
PROTECT
# 事前データ #=> Deletion_model: [{'id': 6, 'protect_row_id': 1, 'name': 'foo'}] ProtectKey.objects.all().delete() #=> ここでエラーを吐く # django.db.models.deletion.ProtectedError: ("Cannot delete some instances of model 'ProtectKey' # because they are referenced through a protected foreign key: # 'DeleteOn.protect_row'", [<DeleteOn: DeleteOn object>])
SET_NULL
# 事前データ #=> Deletion_model: [{'name': 'foo', 'id': 6, 'set_null_row_id': 1}] SetNullKey.objects.all().delete() #=> Deletion_model: [{'name': 'foo', 'id': 6, 'set_null_row_id': None}]
SET_DEFAULT
#=> Deletion_model: [{'id': 8, 'name': 'foo', 'set_default_row_id': 11}] # Modelでは、'default=9' の設定あり SetDefaultKey.objects.filter(name='set_default').delete() #=> Deletion_model: [{'id': 8, 'name': 'foo', 'set_default_row_id': 9}]
SET
#=> Deletion_model: [{'id': 9, 'name': 'foo', 'set_key_row_id': 3}] # Modelでは`on_delete=models.SET(11)`の設定あり SetKey.objects.filter(name='set_row').delete() #=> Deletion_model: [{'id': 9, 'name': 'foo', 'set_key_row_id': 11}]
DO_NOTHING
#=> Deletion_model: [{'do_nothing_row_id': 4, 'id': 11, 'name': 'foo'}] DoNothingKey.objects.filter(name='do_nothing').delete() #=> Deletion_model: [{'do_nothing_row_id': 4, 'id': 11, 'name': 'foo'}]
ソースコード
GitHubに追加してあります。今回のメインはdelete.py
となります。