Django中transaction.atomic回滚时能否修改模型实例状态?订单代码是否可行?
问题解答:Django事务回滚与模型实例状态修改
嘿,这个问题问到点子上了,我来给你拆解清楚:
一、事务回滚时,Django能不能修改模型实例的状态?
得先区分内存中的实例对象和数据库中的记录这两个层面:
- 当
transaction.atomic()触发回滚时,事务内所有数据库操作(创建、更新、删除)都会被撤销,数据库会回到事务开始前的状态。 - 但内存里的模型实例还是存在的,你完全可以修改它的属性值——只不过这个修改只停留在内存里,和数据库已经脱节了。如果实例是事务内创建的,数据库里根本没有对应的记录;如果是事务外创建的,数据库里的记录还是回滚前的状态。
简单说:能改内存中实例的状态,但这个修改不会自动同步到数据库,要是实例对应的数据库记录已经被回滚删除,后续的save()操作还会报错。
二、你提供的代码不可行,原因如下
先看你的代码:
try: with transaction.atomic(): order = Order.objects.create( status='PAYING' ) except Exception as e: order.status = 'FALIED' order.save()
问题核心:当事务因异常回滚时,Order.objects.create()这个操作被彻底撤销了——数据库里根本没有这条订单记录。虽然内存里还留着order实例,但它的id对应的数据库行已经不存在了。这时候调用order.save(),Django会尝试执行UPDATE操作修改一个不存在的记录,直接抛出DoesNotExist异常,根本实现不了你想要的修改状态的目的。
正确的实现思路
你应该把订单创建放在事务外面,先在数据库里生成一条初始状态的订单,再在事务内处理核心业务(比如支付逻辑),失败后再更新订单状态:
# 先创建订单,初始状态设为待处理 order = Order.objects.create(status='CREATED') try: with transaction.atomic(): # 这里执行核心业务逻辑,比如调用支付接口、扣减库存等 # 所有操作成功后,更新订单为支付成功状态 order.status = 'PAID' order.save() except Exception as e: # 事务回滚后,更新订单为失败状态 order.status = 'FAILED' order.save()
这样不管事务是否回滚,订单记录在数据库里都是真实存在的,修改状态后save()就能正常同步到数据库了。另外注意拼写:你代码里的FALIED应该是FAILED,别写错啦😉
内容的提问来源于stack exchange,提问作者HIPPO LD
相关产品推荐
相关产品推荐

