Django中select_for_update在事务内调用工具类失效问题
问题分析与解决方案
问题根源
你调用CustomerService.get_customer时的参数传递方式错误:方法定义中的**params_dict需要接收关键字参数(或通过拆包字典传递),但你直接把查询字典作为位置参数传入,导致两个关键问题:
select_for_update参数被错误赋值为{"id": customer_id}(非空字典会触发if select_for_update:条件);**params_dict没有接收到任何查询参数,最终执行的是Customer.objects.select_for_update().get()——这种写法不仅会查询所有Customer记录,还会因参数异常间接触发事务上下文报错。
而原生ORM查询是直接传递正确的关键字参数,因此能正常运行。
修复方案
1. 修正调用方式
将查询参数以关键字参数传递,或拆包字典:
- 直接传关键字参数:
@transaction.atomic def create(self, request, *args, **kwargs): customer = CustomerService.get_customer(select_for_update=True, id=customer_id)
- 拆包字典传递:
@transaction.atomic def create(self, request, *args, **kwargs): customer = CustomerService.get_customer(select_for_update=True, **{"id": customer_id})
2. 可选:优化工具类方法(避免后续传参错误)
调整方法参数逻辑,强制查询参数通过关键字传递,同时分离select_for_update开关:
class CustomerService: @staticmethod def get_customer(**kwargs) -> Customer: """ param: customer mobile number or other fields return: Customer object raises exception INVALID_CUSTOMER if customer does not exist """ # 从kwargs中取出开关参数,剩余的作为查询条件 select_for_update = kwargs.pop('select_for_update', False) try: customer_qs = Customer.objects if select_for_update: customer_qs = customer_qs.select_for_update() return customer_qs.get(**kwargs) except Customer.DoesNotExist: raise ParseException(INVALID_CUSTOMER, errors='INVALID_CUSTOMER')
优化后的调用更直观:
# 直接传参 customer = CustomerService.get_customer(id=customer_id, select_for_update=True) # 或拆包字典 customer = CustomerService.get_customer(**{"id": customer_id, "select_for_update": True})
内容的提问来源于stack exchange,提问作者raj-kapil
相关产品推荐
相关产品推荐

