如果循环中抛出异常,我试图回滚一组事务。但我不想突破循环或抛出异常而不抓住它。
如果循环中的任何子节点抛出异常,我不希望保存业务逻辑。这意味着我无法将事务放在循环中,因为如果它们中的任何一个失败,它只会回滚特定子项的事务。
parent = Parent.objects.get(pk='something')
exceptions = []
with transaction.atomic():
for child in parent.children.all():
try:
# business logic which also saves other models
# I don't want this saved if there is an exception for any object in the loop
except Exception as e:
exceptions.append({
'id': child.id,
'error': str(e),
})
if len(exceptions) > 0:
transaction.set_rollback(True)
for exception in exceptions:
Child.objects.filter(pk=exception['id']) \
.update(error=exception['error']
# more business logic and raise exception
parent.is_blocked = True
parent.save()
# I don't want this exception to rollback all transactions
raise Exception('Parent {} is blocked'.format(parent.id))
我收到上述代码的错误。这条消息很简单。我试图在块之外回滚事务。
django.db.transaction.TransactionManagementError: The rollback flag doesn't work outside of an 'atomic' block.
有没有人找到办法处理这样的事情。我希望我只是遗漏了一些简单的东西。如果您需要更多信息,请与我们联系。
答案 0 :(得分:1)
Avoid catching exceptions inside atomic!
按照文档进行操作,在特殊情况下,您的代码应如下所示:
parent = Parent.objects.get(pk='something')
exceptions = []
try:
with transaction.atomic():
for child in parent.children.all():
try:
# business logic which also saves other models
# I don't want this saved if there is an exception for any object in the loop
except Exception as e:
exceptions.append({
'id': child.id,
'error': str(e),
})
# raise exception handly to trigger rollback
if len(exceptions) > 0:
raise("raise for rollback")
except Exception as e:
pass
if len(exceptions) > 0:
for exception in exceptions:
Child.objects.filter(pk=exception['id']) \
.update(error=exception['error']
# more business logic and raise exception
parent.is_blocked = True
parent.save()
# I don't want this exception to rollback all transactions
raise Exception('Parent {} is blocked'.format(parent.id))
答案 1 :(得分:0)
您可以尝试生成器功能:
def function():
for child in parent.children.all():
try:
yield result
except Exception as e:
yield exception
为清楚起见,您可以查看此答案: How to handle error thrown in a generator function