【问题标题】:Can't execute queries until end of atomic block in my data migration on django 1.7在 django 1.7 上的数据迁移中,直到原子块结束才能执行查询
【发布时间】:2015-11-19 05:30:30
【问题描述】:

我进行了相当长的数据迁移,以纠正早期的错误迁移,其中某些行创建不正确。我正在尝试根据旧列将值分配给新列,但是,有时这会导致完整性错误。发生这种情况时,我想丢弃导致完整性错误的那个

这是一个代码sn-p:

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

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

【问题讨论】:

    标签: django data-migration


    【解决方案1】:

    这类似于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()
    

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

    【讨论】:

      【解决方案2】:

      每个迁移都围绕一个事务进行,因此当迁移过程中出现故障时,所有操作都将被取消。因此,每个失败的事务都不能接受新的查询(无论如何它们都会被取消)。

      with transaction.atomic(): 包装一些操作不是很好的解决方案,因为当某些操作失败时,您将无法取消该操作。取而代之的是,通过在保存数据之前进行更多检查来避免完整性错误。

      【讨论】:

      • 我不确定为什么使用transaction.atomic() 是一个“糟糕”的解决方案,如果这就是我将要做的事情的话。这些行是错误的,实际上是坏的,我想摆脱它们
      【解决方案3】:

      似乎同一个异常可能有多种原因。就我而言,这是由无效的模型字段名称引起的:我在字段名称中使用了希腊字母 delta ?

      它似乎运行良好,所有应用程序运行良好(也许我只是没有尝试任何更复杂的用例)。然而,测试引发了TransactionManagementError

      我通过从字段名称和所有迁移文件中删除 ? 解决了这个问题。

      【讨论】:

        【解决方案4】:

        我遇到了同样的问题,但我通过使用 django.test.TransactionTestCase 而不是 django.test.TestCase 解决了它。

        【讨论】:

          猜你喜欢
          • 2017-10-14
          • 2013-08-04
          • 2014-02-22
          • 2019-01-27
          • 2018-08-21
          • 2014-05-28
          • 2014-12-13
          • 2014-10-08
          • 2014-11-13
          相关资源
          最近更新 更多