迁移Django模型的字段名称更改而不会丢失数据

问题描述 投票:35回答:7

我有一个django项目,其数据库表已包含数据。我想更改字段名称而不会丢失该列中的任何数据。我最初的计划是简单地更改模型字段名称,而实际上不会更改数据库表的名称(使用db_column列参数):

原始模型:

class Foo(models.Model):
  orig_name = models.CharField(max_length=50)

新模型:

class Foo(models.Model):
  name = models.CharField(max_length=50, db_column='orig_name')

但是,运行South的schemamigration --auto会生成一个迁移脚本,该脚本将删除原始列orig_name,并添加新列name,这会导致删除该列中数据的不良后果。 (我对South为什么要更改db中的列名也感到困惑,因为我对db_column的理解是,它可以更改模型字段名而不更改数据库表列的名称)。

如果我不能不更改db字段而更改模型字段,我想我可以像这样进行更直接的名称更改:

原始模型:

class Foo(models.Model):
  orig_name = models.CharField(max_length=50)

新模型:

class Foo(models.Model):
  name = models.CharField(max_length=50)

无论我最终使用哪种策略(我都希望使用第一个策略,但会发现第二个策略可以接受),我主要关心的是确保我不会丢失该列中已经存在的数据。

这是否需要多步骤的过程? (例如1.添加列,2.将数据从旧列迁移到新列,以及3.删除原始列)还是可以使用db.alter_column之类的内容更改迁移脚本?

更改列名称时保留该列中数据的最佳方法是什么?

django-models django-south custom-fields customcolumn
7个回答
36
投票

在保留数据库字段的同时更改字段名称

为Django 1.8+添加答案(使用Django本地迁移,而不是South迁移)。

进行迁移,首先添加db_column属性,然后重命名该字段。 Django理解第一个是无操作(因为它更改了db_column使其保持不变),第二个是无操作(因为它没有更改任何模式)。我实际上检查了日志,发现没有架构更改...

operations = [
    migrations.AlterField(
        model_name='mymodel',
        name='oldname',
        field=models.BooleanField(default=False, db_column=b'oldname'),
    ),
    migrations.RenameField(
        model_name='mymodel',
        old_name='oldname',
        new_name='newname',
    ),
]

17
投票

很容易修复。但是您必须自己修改迁移。

而不是删除和添加列,请使用db.rename_column。您只需修改由db.rename_column

创建的迁移

8
投票

UPDATE 2

[

UPDATE

使用

Django 2.0.9

进行了测试,它可以自动检测某个字段是否被重命名,并提供重命名选项,而不是删除并创建一个新字段schemamigration --auto

初始

发布,如果仍然对某人有用。

对于

Django 2.0

+只需重命名模型中的字段enter image description here
to

class Foo(models.Model): orig_name = models.CharField(max_length=50)

现在运行class Foo(models.Model):
    name = models.CharField(max_length=50)
它将通过删除旧字段并添加新字段的操作生成迁移。

继续并将其更改为跟随。

python manage.py makemigrations

现在运行operations = [
    migrations.RenameField(
        model_name='foo',
        old_name='orig_name',
        new_name='name')
]
,它将在数据库中重命名该列而不会丢失数据。

7
投票
实际上,在Django 1.10中,只需在模型中重命名字段,然后运行makemigrations,即可立即识别操作(即,一个字段消失了,另一个字段代替了它:]]

python manage.py migrate


5
投票
我遇到了这种情况。我想更改模型中的字段名称,但保持列名称相同。

1
投票
我在Django 1.7.7上遇到了这种情况。我最终做了对我有用的以下工作。

1
投票
可以在不进行任何手动迁移文件编辑的情况下重命名字段:
© www.soinside.com 2019 - 2024. All rights reserved.