You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Rest Framework如何在同一视图类的不同方法间调用变量

问题分析

你当前的实现存在以下核心问题,导致token无法在get方法中正常使用:

  1. 绝对不要在Web请求逻辑中使用global全局变量存储用户私有数据:Django每个HTTP请求都是独立的线程/进程实例,post和get是两次完全独立的请求,全局变量会在多用户访问时出现串号,且get请求大概率拿不到post存储的全局值。
  2. 序列化器调用逻辑错误:UserAccount序列化器需要传入完整的User实例,不需要单独拆分username、email参数,单个用户实例也不需要加many=True。
  3. 冗余数据库查询:Token.objects.get(key=token).user已经直接返回关联的User对象,不需要再二次查询User表。
  4. 没有异常捕获: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 05:48:03