考虑这个简单的例子:
# a bank account class
class Account:
@transaction.commit_on_success
def withdraw(self, amount):
# code to withdraw money from the account
@transaction.commit_on_success
def add(self, amount):
# code to add money to the account
# somewhere else
@transaction.commit_on_success
def makeMoneyTransaction(src_account, dst_account, amount):
src_account.withdraw(amount)
dst_account.add(amount)
(取自https://code.djangoproject.com/ticket/2227)
如果在 中引发异常,则仍将提交inAccount.add()
的事务并且会丢失金钱,因为 Django 当前不处理嵌套事务。Account.withdraw()
如果不对 Django 应用补丁,我们如何确保提交被发送到数据库,但前提是@transaction.commit_on_success
装饰器下的 main 函数完成而不会引发异常?
我遇到了这个片段:http ://djangosnippets.org/snippets/1343/ ,它似乎可以完成这项工作。如果我使用它,我应该注意什么缺点?
如果您能提供帮助,请提前非常感谢。
PS为了可见性,我正在复制之前引用的代码片段:
def nested_commit_on_success(func):
"""Like commit_on_success, but doesn't commit existing transactions.
This decorator is used to run a function within the scope of a
database transaction, committing the transaction on success and
rolling it back if an exception occurs.
Unlike the standard transaction.commit_on_success decorator, this
version first checks whether a transaction is already active. If so
then it doesn't perform any commits or rollbacks, leaving that up to
whoever is managing the active transaction.
"""
commit_on_success = transaction.commit_on_success(func)
def _nested_commit_on_success(*args, **kwds):
if transaction.is_managed():
return func(*args,**kwds)
else:
return commit_on_success(*args,**kwds)
return transaction.wraps(func)(_nested_commit_on_success)