DRF update_profile接口更新后首次返回旧数据,如何传递更新后的请求到profile接口
问题根源
你遇到的问题是两个原因叠加导致的:
QuerySet.update()方法是直接对数据库执行SQL更新,不会更新当前请求上下文里已经加载到内存的request.user(也就是你self.get_user()拿到的实例)- 你调用
self.profile(request)的时候传入的还是原来的请求对象,里面缓存的用户实例还是更新前的旧数据
解决方案
方案1:更新后主动刷新request里的用户实例(最匹配你的需求)
直接修改request对象内缓存的user属性为最新的数据库数据,再传给self.profile方法即可,修改后的update_profile代码如下:
@action(detail=False, methods=['post'], authentication_classes=(JWTAuthentication, SessionAuthentication)) def update_profile(self, request): profile_serialize = ProfileSerializer(data=request.data) profile_serialize.is_valid(raise_exception=True) user_id = self.get_user().pk AppUser.objects.filter(pk=user_id).update(**profile_serialize.data) # 主动更新request内的user为最新数据 request.user = AppUser.objects.get(pk=user_id) return Response(self.profile(request).data)
方案2:重构代码复用序列化逻辑(更规范,耦合度更低)
不需要二次调用self.profile视图方法,把公共的序列化逻辑抽离出来,更新完成后直接序列化最新的用户实例返回即可:
# 抽离公共的用户资料序列化方法 def get_user_profile_data(self, user): return UserSerializer(user, context={"request": self.request}).data @action(detail=False, methods=['get'], authentication_classes=(JWTAuthentication, SessionAuthentication)) def profile(self, request): user = self.get_user() if not user: raise AuthenticationFailed() return Response( {"status": 200, "message": "Success", "data": self.get_user_profile_data(user)}, status=status.HTTP_200_OK) @action(detail=False, methods=['post'], authentication_classes=(JWTAuthentication, SessionAuthentication)) def update_profile(self, request): profile_serialize = ProfileSerializer(data=request.data) profile_serialize.is_valid(raise_exception=True) user = self.get_user() # 直接更新实例属性后保存,会自动同步当前实例的字段值,无需额外查库 for k, v in profile_serialize.data.items(): setattr(user, k, v) user.save() return Response( {"status": 200, "message": "Success", "data": self.get_user_profile_data(user)}, status=status.HTTP_200_OK )
方案3:修改profile方法强制每次读库(不推荐,性能略差)
如果你不想修改update逻辑,也可以直接调整profile方法的取数逻辑,每次都从数据库拉取最新数据,不使用内存缓存的用户实例:
@action(detail=False, methods=['get'], authentication_classes=(JWTAuthentication, SessionAuthentication)) def profile(self, request): # 每次直接查库拉取最新用户数据,绕过内存缓存 user = AppUser.objects.filter(pk=self.get_user().pk).first() if not user: raise AuthenticationFailed() return Response( {"status": 200, "message": "Success", "data": UserSerializer(user, context={"request": self.request}).data}, status=status.HTTP_200_OK)
内容的提问来源于stack exchange,提问作者Ankit Chaurasia
相关产品推荐
相关产品推荐

