假设我有一个模型 TestModel:
class TestModel(models.Model):
field1 = models.CharField(max_length=255)
field2 = models.IntegerField()
def __str__(self):
return f"{self.field1}"
但是我现在需要将field2的类型更改为Text。为了不丢失TestModel模型中的数据,我需要编写一个数据迁移。
所以我创建了一个新模型 NewTestModel:
class NewTestModel(models.Model):
field1 = models.CharField(max_length=255)
field2 = models.TextField()
def __str__(self):
return f"{self.field1}"
运行
python manage.py makemigrations
命令
在 0006_newtestmodel.py 迁移文件中,我添加了 copy_data 函数并使用
migrations.RunPython(copy_data)
运行它
from django.db import migrations, models
def copy_data(apps, database_schema):
TestModel = apps.get_model("data_migrations", "TestModel")
NewTestModel = apps.get_model("data_migrations", "NewTestModel")
for old_object in TestModel.objects.all():
new_object = NewTestModel(
field1 = old_object.field1,
field2 = old_object.field2
)
new_object.save()
class Migration(migrations.Migration):
dependencies = [
('data_migrations', '0005_testmodel'),
]
operations = [
migrations.CreateModel(
name='NewTestModel',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('field1', models.CharField(max_length=255)),
('field2', models.TextField()),
],
),
migrations.RunPython(copy_data)
]
然后我删除 TestModel 模型并运行迁移命令。
之后,我将 NewTestModel 重命名为 TestModel 并再次运行迁移命令。
一切都按照预期进行。
我做对了吗?
我做对了吗?
是的,但你可以做得更快。事实上,在这里您对每个记录进行一个查询来复制,这意味着如果要迁移的数据很大,则需要数小时甚至数天的时间。在这之间,数据库可能会崩溃。 我们可以批量复制:
def copy_data(apps, database_schema):
TestModel = apps.get_model('data_migrations', 'TestModel')
NewTestModel = apps.get_model('data_migrations', 'NewTestModel')
NewTestModel.objects.bulk_create(
[
NewTestModel(field1=old_object.field1, field2=old_object.field2)
for old_object in TestModel.objects.all()
]
)