簡體   English   中英

django:在transaction.atomic()內部提交和引發

[英]django: commit and raise inside transaction.atomic()

我們正在嘗試從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()被提交。 將它設置在同一原子塊內似乎也是合乎邏輯的,因為我們已經為此對象設置了鎖定行。

有什么想法/模式嗎? 提前致謝!

PS:使用舊的手動交易管理是如此簡單!

PPS我們也對“提前退出”使用例外,並且將其移到一些標志等上會帶來混亂的日志,我個人很想避免這種情況。

假設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仍然具有手動事務管理功能

除了已經發布的答案外,如果您使用嵌套方法在原子鏈中更高位置處啟動原子塊,則可以使用以下方法:

transaction.on_commit(lambda: method_that_raises_exception())

這樣,在提交事務后會引發異常。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM