2016-11-23 62 views
1

我们正试图从commit_manually迁移到atomic,所以我们可以在旧项目中将Django升级到至少1.8。在大多数情况下,我们需要做这样的事情:django:commit和raise inside transaction.atomic()

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.S.旧的手动交易管理非常简单!

P.P.S.我们在“早退”时也使用了例外情况,并且移动到某些标志等会带来日志混乱,我个人很乐意避开它。

回答

1

假设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

+0

感谢凯文,这种方法正是我想到的,并且事实上要避免。 我在考虑手动事务管理,但我们也使用保存点。在这种情况下,atomic()是一件好事。 – saabeilin