丹戈:承诺并在内部筹集资金事务处理.atomic()

2024-05-16 05:39:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我们正在尝试从commit_manually迁移到{},这样我们就可以在遗留项目中将Django升级到至少1.8。在大多数情况下,我们需要这样做:

with transaction.atomic():
    obj = Entity.objects.select_for_update().get(pk=pk)
    try:
        obj.do_something()
        obj.set_some_status()
        obj.save()
    except SomeException:
        obj.set_failed_flag()
        obj.save()
        raise

因为被调用方需要此异常信息来继续特定流。但在本例中,事务/保存点将被回滚,这不是我们想要的,因为我们希望obj.set_failed_flag()被提交。同样,将它设置在同一个原子块中似乎是合乎逻辑的,因为我们已经为这个对象锁定了一行。在

有什么想法/模式吗?提前谢谢!在

另外,旧的手工交易管理非常简单!在

p.p.S.我们在“提前退出”和移动到某些旗帜等情况下也使用了例外情况,这会带来一系列混乱,我个人很乐意避免。在


Tags: 项目djangoobjsavewith情况中将flag
2条回答

假设SomeException不是数据库异常,您只需保存它并在原子块外引发它:

with transaction.atomic():
    obj = Entity.objects.select_for_update().get(pk=pk)

    try:
        obj.do_something()
        obj.set_some_status()
    except SomeException as e:
        obj.set_failed_flag()
        exception = e
    else:
        exception = None

    obj.save()

if exception:
    raise exception

如果您觉得这太冗长,并且需要经常这样做,那么您可以编写一个上下文管理器,它充当transaction.atomic()的代理,但在某些情况下不会触发回滚。在

最后,注意Django仍然有manual transaction management。在

除了已经发布的答案之外,如果有嵌套方法,您可以在链的某个更高的位置启动原子块,那么可以使用以下方法:

transaction.on_commit(lambda: method_that_raises_exception())

这样,在提交事务后引发异常。在

相关问题 更多 >