我是否以正确的方式编写了数据类型更改的数据迁移?

问题描述 投票:0回答:1

假设我有一个模型 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 并再次运行迁移命令。

一切都按照预期进行。

我做对了吗?

python django database-migration data-migration
1个回答
0
投票

我做对了吗?

是的,但你可以做得更快。事实上,在这里您对每个记录进行一个查询来复制,这意味着如果要迁移的数据很大,则需要数小时甚至数天的时间。在这之间,数据库可能会崩溃。 我们可以批量复制:

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() ] )

	
© www.soinside.com 2019 - 2024. All rights reserved.