Django - 在引发错误后对transaction.atomic块中的数据库进行操作

问题描述 投票:3回答:1

我想在transaction.atomic()块中对我的数据库执行操作,即使出现错误也是如此。以下是一些示例代码来演示我的问题:

示例代码

# Outer try block
try:

    # Enclose in atomic transaction for database rollbacks
    with transaction.atomic():

        # If this line fails, all database updates within the outer try: block should be rolled back
        u = UU.create(email='[email protected]')

        # Inner try block
        try:
            cc = CC.objects.get(id=1)
            perform_action(cc)

        # If this exception triggers, the 'cc' object should be deleted, but all other database updates within the outer try: block should be rolled back
        except:
            cc.delete()
            raise

        # If this line fails, all database updates within the outer try: block should be rolled back
        u = UU.create(email='[email protected]')

# If any exception triggers, this error should be printed
except:
    print("Error occured.")

如果我的内部try:块中发生错误,我希望删除cc对象,但要回滚外部try:块中的所有其他数据库事务。但是,正如代码现在所示,如果内部cc.delete()块中发生任何错误,try:事务将被回滚。

有什么建议?

django exception transactions atomic atomicity
1个回答
3
投票

您不能只保留数据库事务的一部分,并且在回滚外部事务时不能保留内部事务。

相反,您可以使用自定义异常发出特定错误状态的信号,然后在回滚后捕获它时执行其他处理。就像是:

class BadCCException(Exception):
    def __init__(self, badid):
        super().__init__()
        self.badid = badid

try:
    with transaction.atomic():
        u = UU.create(email='[email protected]')

        try:
            cc = CC.objects.get(id=1)
            perform_action(cc)
        except Exception as e:
            raise BadCCException(1) from e

        u = UU.create(email='[email protected]')
except BadCCException as e:
    CC.objects.filter(id=e.badid).delete()
    print("Error occured.")
except:
    print("Error occured.")
© www.soinside.com 2019 - 2024. All rights reserved.