重命名Django模型而不破坏已有的迁移



我想在Django 3.2中重命名一个模型,保留我现有的迁移,并且能够用旧的表名迁移db和从头创建db。

我已经开始重命名模型类和代码中对它的所有引用。As "/manage.py makemigrations&;没有自动创建迁移,我手动创建了一个重命名模型的迁移:

from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('market_integrations', '0003_migration'),
]
operations = [
migrations.RenameModel('OldModelName', 'NewModelname')
]

我最初的想法是我不应该更新现有的迁移,因为我在创建其他迁移时从不这样做。但是,当我运行"/manage.py migrate"时,对旧迁移中旧模型的引用会导致LookupError。我尝试使用模型名称字符串和apps.get_model()。迁移代码示例:

operations = [
migrations.CreateModel(
name="OldModelName",
...
)
]

operations = [
migrations.CreateModel(
name=apps.get_model("myapp", "OldModelName"),
...
)
]

由于在旧的迁移中保持旧的模型名称不起作用,所以我用新名称替换了旧迁移中的旧模型名称。之后,输入"/manage.py migrate"成功运行,包括模型重命名迁移。但是,当我尝试创建一个新数据库时,模型重命名迁移失败,因为新数据库中从来没有使用旧名称的表。

我应该做些什么才能保留我的迁移并使它们在现有和新数据库中都能工作?

我已经检查了Django的迁移策略来重命名模型和关系字段,但是我没有找到我问题的答案。

请附上完整的模型(你可以删除不相关的字段)和你在最初的问题中创建的迁移(我还不能评论你最初的帖子,所以我不得不在回答中提到它)。

这很重要,因为我认为有外键指向要重命名的模型。或者您正在尝试将Foo重命名为Bar并创建一个新的Foo吗?

如果您尝试在初始想法之后启动服务器,是否也会出现错误?保持现有迁移不变的最初想法似乎很好,因为您将能够在所有环境(本地、开发、prod等)上运行它,而方法2将需要手动重命名数据库表和字段。

在您提供模型和迁移之后,我可能可以扩展我的答案。

migrations.RenameModel(
old_name="ModelA",
new_name="ModelB",
),
migrations.AlterField(
model_name="myrelatedmodel",
name="somefieldname",
field=models.ForeignKey(
# change the properties accordingly (best copy it over). The database may only change to="table"
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="myapp.modelb",
),
),

如果这不起作用,错误是从哪里来的?您可以尝试将您的迁移和模型与其他代码隔离开来(就像在附加到相同数据库的新空项目中一样)。也许这将帮助您找出错误是来自对OldModelName的剩余引用还是一些奇怪的错误。只是作为一个想法,这样你就不会把时间花在看错误的地方

尝试一次做一个更改和一个迁移。稍后你可以把它们压扁。如果django没有自动检测模型的重命名,这意味着与该模型相关的所有字段也会失败。

  1. 在重命名
  2. 之前将所有内容恢复到工作状态
  3. 确保所有迁移都被应用
  4. 重命名模型,并创建一个只重命名模型的迁移。你能应用它吗?
  5. 如果没有,尝试手动修改所有相关字段(one2one,外键等)

如果仍然失败,在models.py中创建模型的副本,重命名复制的模型,并尝试在新的迁移文件中使用migrations.RunPython()将旧表中的所有数据复制到新表中。

如果只有一个已填充的数据库,则可以用ModelB替换所有ModelA,并更改数据库的结构。

祝你好运!

最新更新