简体   繁体   English

为什么我的模型的“on_delete = models.CASCADE”不生成级联外键约束?

[英]Why doesn't my model's “on_delete=models.CASCADE,” generate a cascading foreign key constraint?

I am using Django, Python 3.7, and PostgreSQL 9.5. 我正在使用Django,Python 3.7和PostgreSQL 9.5。 How do I mark up my model such taht a cascading foreign key constraint gets generated? 如何标记我的模型,以便生成级联外键约束? I currently have this in my models.py file ... 我目前在models.py文件中有这个...

class ArticleStat(models.Model):
    article = models.ForeignKey(Article, on_delete=models.CASCADE, )

When I run make migrations my_project in the management console, it produces a file that contains this ... 当我在管理控制台中运行make migrations my_project时,它会生成一个包含此文件的文件...

    migrations.CreateModel(
        name='ArticleStat',
        fields=[
            ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
            ...
            ('article', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='my_project.Article')),
        ],
    ),

However, when I run the migration (using migrate my_project 0001 ), the resulting foreign key does not contain a cascade delete constraint. 但是,当我运行迁移(使用migrate my_project 0001 )时,生成的外键不包含级联删除约束。 This is what the description looks like in PostgreSQL ... 这就是PostgreSQL中的描述......

"my_project_articlesta_article_id_a02a5add_fk_my_project" FOREIGN KEY (article_id) REFERENCES my_project_article(id) DEFERRABLE INITIALLY DEFERRED

How else can I get my models.py file to output a cascading delete foreign key constraint? 我怎么能得到我的models.py文件输出级联删除外键约束?

As described in the django documentation of ForeignKey django merely emulates this behaviour instead of deferring it to the database. ForeignKey django的django文档中所述仅仅模拟此行为而不是将其推迟到数据库。

Django emulates the behavior of the SQL constraint ON DELETE CASCADE and also deletes the object containing the ForeignKey. Django模拟SQL约束ON DELETE CASCADE的行为,并删除包含ForeignKey的对象。

So to answer your question: This is expected behavior and will still work just like you would expect it to work on the database level. 所以回答你的问题:这是预期的行为,并且仍然会像你期望它在数据库级别上工作一样工作。

How else can I get my models.py file to output a cascading delete foreign key constraint? 我怎么能得到我的models.py文件输出级联删除外键约束?

You can't as django currently does not support this feature. 您不能因为django目前不支持此功能。 However there is a ticket discussing to add it: https://code.djangoproject.com/ticket/21961 但是有一张票要讨论添加它: https//code.djangoproject.com/ticket/21961


Edit for further clarification on how to enforce this at database-level 编辑以进一步说明如何在数据库级别强制执行此操作

While I highly recommend to just let django handle this for you there might be reasons not to do so. 虽然我强烈建议让django为你处理这个,但可能有理由不这样做。

To opt out of database table creation or deletion operations you can set Options.managed to False in the Meta class of ArticleStat . 要退出数据库表创建或删除操作,可以在ArticleStatMeta类中将Options.managed设置为False That would however also mean that you are now responsible to do the migrations manually eg writing the CREATE TABLE statement to define the table including the foreign key constraint (which you thus have full control over now). 但这也意味着您现在负责手动执行迁移,例如编写CREATE TABLE语句来定义包含外键约束的表(因此您可以完全控制它)。 Another consideration to take into account is that you should instruct django to not do anything on deletion of a referenced Article object anymore (as your database is now responsible for that). 要考虑的另一个考虑因素是,您应该指示django不再对删除引用的Article对象做任何事情(因为您的数据库现在对此负责)。 That can be ensured by setting on_delete to models.DO_NOTHING . 通过将on_delete设置为models.DO_NOTHING可以确保这一点

Put together your ArticleStat would now look like this: ArticleStat放在一起现在看起来像这样:

class ArticleStat(models.Model):
    article = models.ForeignKey(Article, on_delete=models.DO_NOTHING)

    class Meta:
        managed = False

A comment about signals prompted me to revisit this and list some pitfalls to consider. 关于信号的评论促使我重新审视并列出了一些需要考虑的陷阱。

  • opting out means opting out of django signals as well. 选择退出意味着选择退出django信号。 In particular pre_delete and post_delete won't be fired for cascaded objects anymore. 特别是不再为级联对象触发pre_deletepost_delete

  • As mentioned in the ticket description mixing database- and django-cascading won't play nicely together. 正如票证说明中所提到的,混合数据库和django-cascading不能很好地融合在一起。

    If a model A references a model B using CASCADE_DB, but model B references model C using regular CASCADE, a deletion of A won't cascade all the way to C. 如果模型A使用CASCADE_DB引用模型B,但模型B使用常规CASCADE引用模型C,则删除A将不会一直级联到C.

That being said I couldn't find any definite proof of why django is handling this the way it does currently. 话虽如此,我找不到任何明确的证据,说明为什么django正在以目前的方式处理它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Django 模型 - 如何取消 on_delete=models.CASCADE - Django models - how to cancel on_delete=models.CASCADE Django 正确使用 Models.Cascade (on_delete) - Django Correct Usage of Models.Cascade (on_delete) Django on_delete=models.CASCADE 在 SQL 级别没有影响 - Django on_delete=models.CASCADE has no effect at SQL level on_delete=models.PROTECT 和 on_delete=models.CASCADE 对 Django 模型有什么作用? - what does on_delete=models.PROTECT and on_delete=models.CASCADE do on Django models? 'OperationalError ' 当我插入时: owner = models.ForeignKey(User,on_delete=models.CASCADE) - 'OperationalError ' when I insert : owner = models.ForeignKey(User,on_delete=models.CASCADE) 除了models.CASCADE 用于Django 模型中的ForeignKey 之外,还有其他on_delete 选项吗? - Is there any other option for on_delete other than models.CASCADE for a ForeignKey in Django models? 不使用 user = models.OneToOneField(User,on_delete=models.CASCADE) - Not using user = models.OneToOneField(User,on_delete=models.CASCADE) Django on_delete=models.CASCADE 在使用相关名称时不起作用 - Django on_delete=models.CASCADE not working when using related_name 我们可以只定义models.CASCADE而不使用on_delete吗? - Can we define models.CASCADE only without using on_delete? 为什么 Django 没有 on_update=models.CASCADE 选项? - Why Django doesn't have an on_update=models.CASCADE option?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM