@AnujGuptaの答えは正しいと思います。ただし、ロールバック自体がキャッチして処理する必要のある例外を発生させる可能性があります。
from django.db import transaction, DatabaseError
try:
a.save()
except DatabaseError:
try:
transaction.rollback()
except transaction.TransactionManagementError:
# Log or handle otherwise
このコードをさまざまなsave()
場所で書き換えている場合は、extract-methodを実行できます。
import traceback
def try_rolling_back():
try:
transaction.rollback()
log.warning('rolled back') # example handling
except transaction.TransactionManagementError:
log.exception(traceback.format_exc()) # example handling
最後に、以下を使用するメソッドを保護するデコレータを使用して、それを偽装できますsave()
。
from functools import wraps
def try_rolling_back_on_exception(fn):
@wraps(fn)
def wrapped(*args, **kwargs):
try:
return fn(*args, **kwargs)
except:
traceback.print_exc()
try_rolling_back()
return wrapped
@try_rolling_back_on_exception
def some_saving_method():
# ...
model.save()
# ...
上記のデコレーターを実装したtry_rolling_back()
としても、特定の処理が必要で、汎用的なデコレーターの処理では不十分な場合に手動で使用する必要がある場合に備えて、抽出されたメソッドとして保持しておくと便利です。