我要进行相当长时间的数据迁移,以纠正早期的错误迁移,其中错误地创建了一些行。我试图基于旧值将值分配给新列,但是,有时这会导致完整性错误。发生这种情况时,我想扔掉导致完整性错误的那个

这是一个代码片段:

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


然后在我的Migration类的操作中

operations = [
    migrations.RunPython(load_data)
]


运行迁移时出现以下错误

django.db.transaction.TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block


我有做的感觉

with transaction.atomic():


我的解决方案是在某个地方,但我不确定确切位置在哪里。更重要的是,我想了解为什么这是必要的

最佳答案

这与example in the docs相似。

首先,添加所需的导入(如果尚未导入)。

from django.db import transaction


然后,将可能引起完整性错误的代码包装在原子块中。

try:
    with transaction.atomic():
        inst.new_col = new_col_mapping[c]
        inst.save()
except IntegrityError:
    inst.delete()


错误的原因在警告块“避免在atomic内捕获异常!”中进行了说明。在文档中。 Django遇到数据库错误后,它将回滚原子块。尝试任何更多的数据库查询都将导致您看到一个TransactionManagementError。通过将代码包装在原子块中,仅该代码将被回滚,并且您可以在块外执行查询。

10-08 07:41
查看更多