Django Rest Framework如何在同一视图类的不同方法间调用变量
问题分析
你当前的实现存在以下核心问题,导致token无法在get方法中正常使用:
- 绝对不要在Web请求逻辑中使用global全局变量存储用户私有数据:Django每个HTTP请求都是独立的线程/进程实例,post和get是两次完全独立的请求,全局变量会在多用户访问时出现串号,且get请求大概率拿不到post存储的全局值。
- 序列化器调用逻辑错误:
UserAccount序列化器需要传入完整的User实例,不需要单独拆分username、email参数,单个用户实例也不需要加many=True。 - 冗余数据库查询:
Token.objects.get(key=token).user已经直接返回关联的User对象,不需要再二次查询User表。 - 没有异常捕获:token无效、不存在的场景会直接返回500错误,没有做权限校验。
修正方案
方案1:标准REST Token认证(最推荐)
常规的Token认证不需要单独做POST接口传token,直接让前端在GET请求的请求头中携带Authorization字段即可,格式为Bearer <你的token值>,DRF自带的TokenAuthentication会自动完成用户识别:
第一步:配置settings.py
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'rest_framework.authentication.TokenAuthentication', ], 'DEFAULT_PERMISSION_CLASSES': [ 'rest_framework.permissions.IsAuthenticated', ] }
第二步:修改视图代码
class UserDetails(APIView): authentication_classes = [TokenAuthentication] permission_classes = [IsAuthenticated] def get(self, request): # DRF自动通过请求头的token识别用户,直接取request.user即可 serializer = UserAccount(instance=request.user) return Response(serializer.data)
第三步:调整urls.py
只需要保留一个接口即可,多余的post接口可以删除:
path('get-user-details/', views.UserDetails.as_view()),
方案2:保留现有POST传Token + GET取数据的逻辑
如果你必须要按当前的双接口逻辑实现,就用Django自带的session存储token,session和用户客户端绑定,不会出现串号问题:
修改后视图代码
class UserDetails(APIView): # POST接口:接收token存入session def post(self, request, *args): serializer = UserAccountTokenSendSerializer(data=request.data) if serializer.is_valid(raise_exception=True): token = serializer.validated_data['token'] # 校验token有效性 try: Token.objects.get(key=token) except Token.DoesNotExist: return Response({"error": "无效的token"}, status=401) # 存入当前用户的session中 request.session['user_token'] = token return Response({"msg": "token存储成功"}) return Response(serializer.errors, status=400) # GET接口:从session取token查询用户数据 def get(self, request): token = request.session.get('user_token') if not token: return Response({"error": "请先提交token"}, status=400) try: user = Token.objects.get(key=token).user except Token.DoesNotExist: return Response({"error": "无效的token"}, status=401) serializer = UserAccount(instance=user) return Response(serializer.data)
urls.py无需修改,保持你原有的两个路径即可。
其他优化点
- 你定义的
UserAccountTokenSend模型完全没有必要,不需要存前端传的token,直接用DRF自带的Token表校验即可,可以删掉这个模型和对应的序列化器。 - 所有数据库查询操作都要加异常捕获,避免无效请求触发服务端500错误。
内容的提问来源于stack exchange,提问作者Ivan Stepanchuk
相关产品推荐
相关产品推荐

