我有一个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 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',
),
]
很容易修复。但是您必须自己修改迁移。
而不是删除和添加列,请使用db.rename_column
。您只需修改由db.rename_column
UPDATE 2
[ UPDATE Django 2.0.9 初始schemamigration --auto
对于
Django 2.0
+只需重命名模型中的字段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')
]
,它将在数据库中重命名该列而不会丢失数据。
python manage.py migrate