transaction.atomic() 如果执行另一个查询会回滚

1 投票
1 回答
35 浏览
提问于 2025-04-14 17:35

我在使用 Djangotransaction.atomic 时遇到了一些问题。我有一个应用,用户可以更新他们的信息,这里我用 年龄 来举例,但实际上可能是像账户余额这样的东西。

我想防止在同时收到多个请求时更新这个字段,所以我想锁定这一行数据,这就是我使用 transaction.atomicselect_for_update 的原因。我有一个 UserProfile 模型,我想更新一些信息,下面是我用来更新的方法:

Class Profile(models.Model):
    def get_queryset(self):
        return self.__class__.objects.filter(id=self.id)

    @transaction.atomic()
    def update_age(
        self,
        age: int,
    ) -> None:
        obj = self.get_queryset().select_for_update().get()
        obj.age = age
        obj.save()

下面是视图部分

class UserProfileView(APIView):
    
    def put(self, request):
        profile = rquest.user.profile
        profile.update_age(request.data["age"])
    
        UpdateHistory.objects.create(user=request.user, updated_field="age")

问题是 UpdateHistory 对象被创建了,但 年龄 的更新却被回滚了。不过当我去掉创建 UpdateHistory 的代码时,年龄 就能成功更新。所以上面的代码只创建了 UpdateHistory,却没有更新 UserProfile.age。如果我去掉这一行 UpdateHistory.objects.create(user=request.user, updated_field="age"),那么 年龄 就能成功更新。

没有任何异常被抛出,这让我困惑了好几天。希望能得到一些帮助。提前谢谢!

1 个回答

0

我本来会直接用一个叫做 django 的 update 方法:

self.get_queryset().update(age=age)

撰写回答