在Django中实现ON DELETE CASCADE逻辑在哪里? (使用PostgreSQL)

时间:2021-09-14 10:34:11

I just need a confirmation for my understanding on Django's implementation of ON DELETE CASCADE from you Django experts.

我只需要确认我对Django从Django专家那里实现ON DELETE CASCADE的理解。

According to the official Django documentation:

根据官方Django文档:

When Django deletes an object, by default it emulates the behavior of the SQL constraint ON DELETE CASCADE -- in other words, any objects which had foreign keys pointing at the object to be deleted will be deleted along with it.

当Django删除一个对象时,默认情况下它会模拟SQL约束ON DELETE CASCADE的行为 - 换句话说,任何具有指向要删除的对象的外键的对象都将随之删除。

Does the word "emulate" imply that the ON DELETE CASCADE logic is actually implemented in Django instead of at the database level? (I looked into my database and all the tables that contains foreign keys have ON DELETE NO ACTION in their definitions.)

“模拟”一词是否意味着ON DELETE CASCADE逻辑实际上是在Django而不是在数据库级别实现的? (我查看了我的数据库,所有包含外键的表在其定义中都有ON DELETE NO ACTION。)

If my understanding is correct, is there any way that I can relocate the ON DELETE CASCADE logic from the app layer to the database layer? I am more looking for a proper way, not an hack, of doing this. (Note: I am using PostgreSQL as my backend.)

如果我的理解是正确的,有没有办法可以将ON DELETE CASCADE逻辑从app层重新定位到数据库层?我正在寻找一种正确的方式,而不是黑客,这样做。 (注意:我使用PostgreSQL作为我的后端。)

2 个解决方案

#1


6  

If you are asking where the relevant code is implemented: You can find it here.

如果您询问相关代码的实现位置:您可以在此处找到它。

Implementing the CASCADE-DELETE logic in the application/ORM layer makes sense as this enables the app to get informed when deletion happens (eg. Django's delete signals are fired for the deleted instances), furthermore it is a sane way to enable this feature across different types of databases.

在应用程序/ ORM层中实现CASCADE-DELETE逻辑是有意义的,因为这使得应用程序在删除发生时得到通知(例如,Django的删除信号被删除的实例被触发),而且这是一种理智的方式来启用此功能不同类型的数据库。

If you are worried about the integrity of your data: Django still sets foreign key constraints if your database supports this (eg. check Postgresql). So your database won't let you delete any rows a foreign key is pointing to.

如果您担心数据的完整性:如果您的数据库支持,Django仍设置外键约束(例如,检查Postgresql)。因此,您的数据库不允许您删除外键指向的任何行。

Try it yourself:

亲自尝试一下:

> DELETE FROM accounts_publisher WHERE id=5;
ERROR:  update or delete on table "accounts_publisher" violates foreign key constraint "accounts_publisher_id_411559b18a178e73_fk_accounts_publisher_id" on table "accounts_membership"
DETAIL:  Key (id)=(5) is still referenced from table "accounts_membership".

#2


0  

FYI, this has been configurable since django 1.3: https://docs.djangoproject.com/en/1.6/ref/models/fields/#django.db.models.ForeignKey.on_delete

仅供参考,自django 1.3以来这已经可配置:https://docs.djangoproject.com/en/1.6/ref/models/fields/#django.db.models.ForeignKey.on_delete

Basically you need to set on_delete to DO_NOTHING and add the cascade logic to the DB yourself:

基本上你需要将on_delete设置为DO_NOTHING并自己将级联逻辑添加到DB:

DO_NOTHING: Take no action. If your database backend enforces referential integrity, this will cause an IntegrityError unless you manually add a SQL ON DELETE constraint to the database field (perhaps using initial sql).

DO_NOTHING:不采取任何行动。如果数据库后端强制实施参照完整性,则会导致IntegrityError,除非您手动将SQL ON DELETE约束添加到数据库字段(可能使用初始sql)。

#1


6  

If you are asking where the relevant code is implemented: You can find it here.

如果您询问相关代码的实现位置:您可以在此处找到它。

Implementing the CASCADE-DELETE logic in the application/ORM layer makes sense as this enables the app to get informed when deletion happens (eg. Django's delete signals are fired for the deleted instances), furthermore it is a sane way to enable this feature across different types of databases.

在应用程序/ ORM层中实现CASCADE-DELETE逻辑是有意义的,因为这使得应用程序在删除发生时得到通知(例如,Django的删除信号被删除的实例被触发),而且这是一种理智的方式来启用此功能不同类型的数据库。

If you are worried about the integrity of your data: Django still sets foreign key constraints if your database supports this (eg. check Postgresql). So your database won't let you delete any rows a foreign key is pointing to.

如果您担心数据的完整性:如果您的数据库支持,Django仍设置外键约束(例如,检查Postgresql)。因此,您的数据库不允许您删除外键指向的任何行。

Try it yourself:

亲自尝试一下:

> DELETE FROM accounts_publisher WHERE id=5;
ERROR:  update or delete on table "accounts_publisher" violates foreign key constraint "accounts_publisher_id_411559b18a178e73_fk_accounts_publisher_id" on table "accounts_membership"
DETAIL:  Key (id)=(5) is still referenced from table "accounts_membership".

#2


0  

FYI, this has been configurable since django 1.3: https://docs.djangoproject.com/en/1.6/ref/models/fields/#django.db.models.ForeignKey.on_delete

仅供参考,自django 1.3以来这已经可配置:https://docs.djangoproject.com/en/1.6/ref/models/fields/#django.db.models.ForeignKey.on_delete

Basically you need to set on_delete to DO_NOTHING and add the cascade logic to the DB yourself:

基本上你需要将on_delete设置为DO_NOTHING并自己将级联逻辑添加到DB:

DO_NOTHING: Take no action. If your database backend enforces referential integrity, this will cause an IntegrityError unless you manually add a SQL ON DELETE constraint to the database field (perhaps using initial sql).

DO_NOTHING:不采取任何行动。如果数据库后端强制实施参照完整性,则会导致IntegrityError,除非您手动将SQL ON DELETE约束添加到数据库字段(可能使用初始sql)。