在django 1.7上的数据迁移中,直到原子块结束才能执行查询

sed*_*idw 8 django data-migration

我有一个很长的数据迁移,我正在做的是纠正早期的错误迁移,其中某些行创建不正确.我正在尝试根据旧列为新列分配值,但是,有时这会导致完整性错误.当发生这种情况时,我想扔掉造成完整性错误的那个

这是一段代码:

def load_data(apps, schema_editor):
    MyClass = apps.get_model('my_app', 'MyClass')

    new_col_mapping = {old_val1: new_val1, ....}

    for inst in MyClass.objects.filter(old_col=c):

        try:
            inst.new_col = new_col_mapping[c]
            inst.save()

        except IntegrityError:
            inst.delete()
Run Code Online (Sandbox Code Playgroud)

然后在我Migration班上的操作中我做

operations = [
    migrations.RunPython(load_data)
]
Run Code Online (Sandbox Code Playgroud)

运行迁移时出现以下错误

django.db.transaction.TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block
Run Code Online (Sandbox Code Playgroud)

我觉得这样做

with transaction.atomic():
Run Code Online (Sandbox Code Playgroud)

某处是我的解决方案,但我不确定正确的地方在哪里.更重要的是,我想了解为什么这是必要的

Ala*_*air 22

这类似于文档中示例.

首先,如果您还没有,请添加所需的导入.

from django.db import transaction
Run Code Online (Sandbox Code Playgroud)

然后包装可能在原子块中引发完整性错误的代码.

try:
    with transaction.atomic():
        inst.new_col = new_col_mapping[c]
        inst.save()
except IntegrityError:
    inst.delete()
Run Code Online (Sandbox Code Playgroud)

警告块"避免在原子内捕获异常!"中解释了错误的原因.在文档中.一旦Django遇到数据库错误,它将回滚原子块.尝试更多的数据库查询将导致TransactionManagementError您看到的.通过将代码包装在原子块中,只会回滚该代码,并且可以在块之外执行查询.