如何使您的自定义Django迁移可逆?

发布于 2025-01-21 01:19:38 字数 1684 浏览 1 评论 0原文

我最初的问题是,给定一个包含 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() 函数中添加新字段。

创建备份字段的想法是将数据库恢复到之前的状态。

鉴于该表中有 60M 行,这是正确的方法吗?不会暂时锁表吧?我想尽可能高效地做到这一点

My original problem was, given a db table with 60M rows I need to convert a field type from boolean to integer field. I thought of creating a custom django migration for this (please do let me know if you have a better approach than this) which looks like this-

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',
        ),
    ]


I want to unroll all the changes i.e., making my custom migration reversible.
I have gone through RunPython doc. But I am confused as in how can i perform addition of a new field in my reverse_code() function.

The idea of creating a backup field is to reinstate the db to its previous state.

Is this is the correct approach, given I have 60M rows in that table? wouldn't it lock the table for the time being? I want to do this as efficient as possible

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

遇到 2025-01-28 01:19:38

在您的评论之后,我编辑了答案 - 当Runpython在归还步骤中执行时,charging_status已重命名为chode> chody> charging_status_v2 和old old <代码> 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',
        ),
    ]

i edited my answer after your comments - at the moment when RunPython is executed in reversion step, charging_status has been renamed to charging_status_v2 and the old charging_status field is present. So you can copy directly from backup to 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',
        ),
    ]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文