我们正在尝试从commit_manually
迁移到atomic
,因此我们可以在遗留项目中将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.S。旧手动交易管理很容易!
P.P.S。我们也使用例外来“提前退出”并转移到一些旗帜等会带来一堆乱七八糟的东西,我个人很乐意避免它。
答案 0 :(得分:1)
假设CallbackPath
不是数据库异常,您只需保存它并将其提升到原子块之外:
/umbraco/surface/UmbracoIdentityAccount/LinkLoginCallback
如果您发现这个过于冗长且需要经常执行,您可能可以编写一个上下文管理器作为SomeException
的代理,但在某些情况下不会触发回滚。
最后,请注意Django仍有manual transaction management。
答案 1 :(得分:1)
除了已经发布的答案,如果有嵌套方法,你在链中更高的位置启动原子块,它有助于使用以下内容:
transaction.on_commit(lambda: method_that_raises_exception())
这样就会在事务提交后引发异常。