在不破坏现有迁移的情况下重命名 Django 模型
Posted
技术标签:
【中文标题】在不破坏现有迁移的情况下重命名 Django 模型【英文标题】:Renaming Django model without breaking existing migrations 【发布时间】:2021-10-12 03:53:20 【问题描述】:我想在 Django 3.2 中重命名一个模型,保留我现有的迁移,并且能够迁移具有旧表名的数据库并从头开始创建一个数据库。
我首先重命名了模型类以及代码中对它的所有引用。由于“./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 migration strategy for renaming a model and relationship fields,但我没有在那里找到我的问题的答案。
【问题讨论】:
【参考方案1】:请附上完整的模型(您可以删除不相关的字段)和您在初始问题中创建的迁移(我还不能评论您的初始帖子,所以我必须在答案中提及)。
这很重要,因为我认为有外键指向您要重命名的模型。 或者您是否尝试将 Foo 重命名为 Bar 并创建一个 new Foo?
如果您在最初的想法之后尝试启动服务器,是否也会出现错误? 您保持现有迁移不变的最初想法似乎很好,因为您将能够在所有环境(本地、开发、生产等)上运行它,并且方法 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 没有自动检测模型的重命名,则意味着与该模型相关的所有字段也会失败。
-
在重命名之前将所有内容恢复到工作状态
确保应用所有迁移
重命名模型并创建迁移以仅重命名模型。你能申请吗?
如果没有,请尝试手动修改所有相关字段(one2one、foreignkey 等)
如果仍然失败,请在 models.py 中创建模型的副本,重命名复制的模型并尝试在新的迁移文件中使用 migrations.RunPython()
将旧表中的所有数据复制到新表中。
如果您只有一个填充的数据库,您可能会用 ModelB 替换所有出现的 ModelA 并更改数据库的结构。
祝你好运!
【讨论】:
以上是关于在不破坏现有迁移的情况下重命名 Django 模型的主要内容,如果未能解决你的问题,请参考以下文章