Правильно ли я написал миграцию данных для изменения типа данных?
Допустим, у меня есть модель TestModel:
class TestModel(models.Model):
field1 = models.CharField(max_length=255)
field2 = models.IntegerField()
def __str__(self):
return f"{self.field1}"
Но теперь мне нужно изменить тип поля2 на 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()
]
)