2016-11-23 61 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