如何在 Django 1.11 中删除迁移中的内容类型?

问题描述

我有一个模型(我们将其命名为 Material),它最初是在一个整体式应用程序中创建的(我们称之为 A)。为了将这个单体应用按照业务领域逻辑划分成独立的应用,我们在新应用(B)中创建了一个同名的模型,并进行了从A到B的数据迁移,然后我们从应用A中移除了该模型.

在我们的一个视图中,我们使用依赖于 ContentTypes 的元素过滤器来按应用列出模型的名称,为此,我们使用 ContentType.objects.get_for_models() 和类列表(其中包含 B.Material、但不是A.Material),但出现错误

nonetype' object has no attribute '_Meta

这是因为 A.Material 的类从代码中消失了,但仍然存在于 ContentType 表中。当调用 get_for_models() 时,它似乎是 search for combinations of model and app_label 而不是我们提供的列表。 filter() 结果在那里会有 A.Material 和 B.Material,后来因为 A.Material 出现错误

虽然我发现 get_for_models() 的行为在这方面很奇怪,但我相信问题是陈旧的 ContentType。有没有一种安全的方法可以通过 Django 1.11 中的迁移自动删除 ContentType?

我尝试在迁移期间调用 .delete(),但迁移后 ContentType 仍然存在。

ContentType = apps.get_model('contenttypes','ContentType')
MaterialModel = apps.get_model('my_app','Material')
ContentType.objects.get_for_model(MaterialModel).delete()

命令 remove_stale_contenttypes 确实将其检测为过时,但我希望在迁移期间完成删除,而无需其他步骤。

解决方法

您可以使用 data migration 删除项目,您可以通过以下方式删除条目:

ContentType = apps.get_model('contenttypes','ContentType')
ContentType.objects.filter(
    app_label='app_label',model='Material'
).delete()

其中 app_label 被替换为第一个应用程序的名称(对于您的问题,应该是 'a')。