【问题标题】:Django does not honor ON DELETE CASCADEDjango 不尊重 ON DELETE CASCADE
【发布时间】:2019-07-12 02:01:24
【问题描述】:

这是我的模型:

class Subscriber(models.Model):
    ...
    tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE, null=True)
    ...

这是生成的 SQL,根据sqlmigrate(以及手动检查数据库):

ALTER TABLE `myapp_subscriber` ADD CONSTRAINT `myapp_subscriber_tenant_id_b52815ee_fk_myapp_tenant_id` FOREIGN KEY (`tenant_id`) REFERENCES `myapp_tenant` (`id`);

我期待类似this:

CREATE TABLE child (
    id INT,
    parent_id INT,
    INDEX par_ind (parent_id),
    FOREIGN KEY (parent_id)
        REFERENCES parent(id)
        ON DELETE CASCADE
) ENGINE=INNODB;

使用ON DELETE CASCADE

MySql(实际上是MariaDB)在我删除时抱怨:

SQL Error (1451): Cannot delete or update a parent row: a foreign key constraint fails

这是有道理的,因为没有ON DELETE CASCADE 子句。

为什么Django 2.1.5 不遵守ON DELETE CASCADE 子句?

【问题讨论】:

  • 你检查过你的数据库权限了吗?

标签: python mysql sql django mariadb


【解决方案1】:

来自docs

on_delete 不会在数据库中创建 SQL 约束。支持 数据库级级联选项可能会在以后实现

它将在 Django 本身中执行级联,因此如果您使用 Django delete() 删除 Tenant 对象,您的 Subscriber 对象也将被删除。但如果您在 SQL 中执行此操作,则不会。

【讨论】:

  • 如果我想在 SQL 级别执行此操作,我有哪些选择?
  • 在什么意义上?您想将约束添加到您的表中以便它始终这样做吗?或者您想要执行删除租户行和级联的 SQL 查询?
  • 这些是我的选择! :) 我会选择第一个,然后用我自己的 hackish 迁移来更改数据库。
  • 您可以在迁移文件中使用RunSQL。但我实际上建议您不要这样做,因为这会给您的应用程序带来意外行为。您不必经常使用需要在数据库级别实现它的原始 SQL。至少,在你的模型中添加一个超级大的超级粗体评论,让未来的同事知道发生了什么:-)
  • 注意:如果您需要手动操作,manage.py shell 是比manage.py dbshell 更好的直接访问对象的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-01
  • 2015-12-31
  • 1970-01-01
  • 2018-12-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多