我正在使用Django,Python 3.7和PostgreSQL 9.5。我该如何标记我的模型,以便生成级联的外键约束?我目前在我的models.py文件中有此文件...
class ArticleStat(models.Model):
article = models.ForeignKey(Article, on_delete=models.CASCADE, )
当我在管理控制台中运行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')),
],
),
但是,当我运行迁移(使用migrate my_project 0001
)时,生成的外键不包含级联删除约束。这就是PostgreSQL中的描述...
"my_project_articlesta_article_id_a02a5add_fk_my_project" FOREIGN KEY (article_id) REFERENCES my_project_article(id) DEFERRABLE INITIALLY DEFERRED
我还能如何获取我的models.py文件以输出级联删除外键约束?
答案 0 :(得分:5)
如django documentation of ForeignKey
django中所述,它只是模拟了这种行为,而不是将其推迟到数据库中。
Django会在DELETE CASCADE上模拟SQL约束的行为,并删除包含ForeignKey的对象。
因此,请回答您的问题:这是预期的行为,并且仍然会像在数据库级别上一样起作用。
我还能如何获取我的models.py文件以输出级联删除外键约束?
您不能这样做,因为django当前不支持此功能。但是,有一张讨论添加它的票证:https://code.djangoproject.com/ticket/21961
虽然我强烈建议您让django为您处理,但可能有理由不这样做。
要选择退出数据库表创建或删除操作,可以在False
的{{1}}类中将Options.managed设置为Meta
。但是,这也意味着您现在有责任手动进行迁移,例如编写ArticleStat
语句以定义包含外键约束的表(因此您现在可以完全控制它)。要考虑的另一个考虑因素是,您应该指示django在删除引用的CREATE TABLE
对象时不再执行任何操作(因为数据库现在对此负责)。可以通过将Article
设置为models.DO_NOTHING来确保这一点。
将您的on_delete
放在一起看起来像这样:
ArticleStat
选择退出也意味着退出Django信号。特别是,class ArticleStat(models.Model):
article = models.ForeignKey(Article, on_delete=models.DO_NOTHING)
class Meta:
managed = False
和pre_delete
将不再为级联对象触发。
如ticket description所述,混合数据库级和Django级联不能很好地发挥作用。
如果模型A使用CASCADE_DB引用了模型B,但是模型B 使用常规CASCADE引用模型C,删除A不会 一直到C。
话虽如此,我找不到任何明确的证据证明django为何以目前的方式进行处理。