Как сделать ваши пользовательские миграции django обратимыми?

Моя первоначальная проблема заключалась в том, что в таблице db с 60M строк мне нужно преобразовать тип поля из булева в целочисленный. Я подумал о создании пользовательской миграции django для этого (пожалуйста, дайте мне знать, если у вас есть лучший подход, чем этот), который выглядит следующим образом-

def make_changes(apps, schema_editor):
    vcs_model = apps.get_model('iot_app', 'AbstractVCSCompartmentData')
    vcs_model.objects.select_related('vcsdata').all().update(charging_status_v2=F('charging_status'))
    vcs_model.objects.select_related('vcsdata').all().update(charging_status_backup=F('charging_status'))  # backup




class Migration(migrations.Migration):
    dependencies = [
        ('iot_app', '0030_auto_20220225_1027.py'),
    ]

    operations = [

        migrations.AddField(  # backup field
            model_name='AbstractVCSCompartmentData',
            name='charging_status_backup',
            field=models.PositiveIntegerField(blank=True, null=True),
        ),


        migrations.AddField(
            model_name='AbstractVCSCompartmentData',
            name='charging_status_v2',
            field=models.PositiveIntegerField(blank=True, null=True),
        ),

        migrations.RunPython(make_changes),

        migrations.RemoveField(
            model_name='AbstractVCSCompartmentData',
            name='charging_status',
        ),
        migrations.RenameField(
            model_name='AbstractVCSCompartmentData',
            old_name='charging_status_v2',
            new_name='charging_status',
        ),
    ]


Я хочу развернуть все изменения, т.е. сделать мой пользовательский переход обратимым. Я просмотрел документ RunPython. Но я запутался, как я могу выполнить добавление нового поля в моей функции reverse_code().

Идея создания резервного поля заключается в восстановлении прежнего состояния базы данных.

я отредактировал свой ответ после ваших комментариев - в момент, когда RunPython выполняется в шаге реверсии, charging_status был переименован в charging_status_v2 и старое поле charging_status присутствует. Таким образом, вы можете копировать непосредственно из резервной копии в charging_status

def make_changes(apps, schema_editor):
    vcs_model = apps.get_model('iot_app', 'AbstractVCSCompartmentData')
    vcs_model.objects.select_related('vcsdata').all().update(charging_status_v2=F('charging_status'))
    vcs_model.objects.select_related('vcsdata').all().update(charging_status_backup=F('charging_status'))  # backup


def backwards(apps, schema_editor):
    vcs_model = apps.get_model('iot_app', 'AbstractVCSCompartmentData')
    vcs_model.objects.select_related('vcsdata').all().update(charging_status=F('charging_status_backup'))



class Migration(migrations.Migration):
    dependencies = [
        ('iot_app', '0030_auto_20220225_1027.py'),
    ]

    operations = [

        migrations.AddField(  # backup field
            model_name='AbstractVCSCompartmentData',
            name='charging_status_backup',
            field=models.PositiveIntegerField(blank=True, null=True),
        ),


        migrations.AddField(
            model_name='AbstractVCSCompartmentData',
            name='charging_status_v2',
            field=models.PositiveIntegerField(blank=True, null=True),
        ),

        migrations.RunPython(make_changes, backwards),

        migrations.RemoveField(
            model_name='AbstractVCSCompartmentData',
            name='charging_status',
        ),
        migrations.RenameField(
            model_name='AbstractVCSCompartmentData',
            old_name='charging_status_v2',
            new_name='charging_status',
        ),
    ]
Вернуться на верх