【问题标题】:Using nested Django transaction.atomic() to handle exceptions?使用嵌套的 Django transaction.atomic() 处理异常?
【发布时间】:2017-07-24 00:59:00
【问题描述】:

Django 的文档对transaction.atomic() 和异常有这样的说法:

https://docs.djangoproject.com/en/1.10/topics/db/transactions/#django.db.transaction.atomic

避免在 atomic 中捕获异常!

...

捕获数据库错误的正确方法是围绕原子块,如上所示。如有必要,为此添加一个额外的原子块。这种模式还有另一个优点:它明确界定了发生异常时将回滚的操作。

...

“如有必要,为此添加一个额外的原子块”是什么意思。看起来像?我可以这样做还是会导致“意外行为”?

valid = True
errors = []
objects = MyModel.objects.all()
try:
    with transaction.atomic():
        for obj in objects:
            try:
                # Update and save obj here...
            except:
                errors.append("obj {} had errors".format(obj.pk))
                valid = False
        if not valid:
            raise Exception('batch update failed.')

except Exception as ex:
    # Handle it..

他们的意思是这样写吗?如果是这样,为什么会有所不同?

valid = True
errors = []
objects = MyModel.objects.all()
try:
    with transaction.atomic():
        for obj in objects:
            try:
                with transaction.atomic():  # Here's my 'extra atomic block'
                    # Update and save obj here...
            except:
                errors.append("obj {} had errors".format(obj.pk))
                valid = False
        if not valid:
            raise Exception('batch update failed.')

except Exception as ex:
    # Handle it..

【问题讨论】:

    标签: python django transactions


    【解决方案1】:

    Django 仅在事务块捕获DatabaseError(或其子类)时触发回滚,因此您不应该在它之前捕获它。如果你添加第二个事务块(你的第二个例子),错误被捕获,事务被标记为回滚,然后你可以做任何你想做的事情。

    我认为你应该很好,你重新提出完全相同的错误,但这只是一个猜测。

    【讨论】:

    • > 抢在它前面?
    • 在您的第一个示例中,您在事务块结束之前捕获了错误,因此事务逻辑不知道出现问题并且不会回滚事务。我希望现在更容易理解了。
    • 明确地说,如果事务块以 any 异常退出,Django 会触发回滚。但是,DatabaseError 表示当前事务存在问题,因此您永远不应该捕获DatabaseError,直到引发它的(最里面的)原子块回滚。对于其他异常,如果您不希望事务回滚,可以在原子块内捕获它们。
    猜你喜欢
    • 2014-03-27
    • 2017-08-25
    • 1970-01-01
    • 1970-01-01
    • 2023-02-10
    • 1970-01-01
    • 1970-01-01
    • 2015-01-10
    • 1970-01-01
    相关资源
    最近更新 更多