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

如何在Django中间件中修改request.user并添加profile属性?

问题根源

你遇到的问题核心是:

  1. 你在Middleware中手动调用JWTAuthentication().authenticate(request)获取用户,但DRF会在视图处理阶段再次执行认证逻辑,将request.user替换为从数据库加载的实际User实例,覆盖了你之前给request.user(此时是SimpleLazyObject懒加载对象)添加的profile属性。
  2. SimpleLazyObject是Django用于延迟加载用户的包装器,当你给它添加属性后,一旦它被解析为真实的User实例,这些额外属性不会自动传递到新的实例上,导致视图中访问request.user.profile时触发属性不存在的错误。
解决方案:自定义JWT认证类

既然DRF会在视图阶段执行认证,我们可以直接在认证过程中给用户实例添加profile属性,确保属性伴随最终的User实例传递到视图中。

步骤1:创建自定义认证类

在users/authentication.py(无则新建)中编写:

from rest_framework_simplejwt.authentication import JWTAuthentication
from users.models import User

class CustomJWTAuthentication(JWTAuthentication):
    def authenticate(self, request):
        # 调用父类方法完成JWT认证,获取用户和token
        user, token = super().authenticate(request)
        
        if user is not None:
            # 从token payload中获取profile_type
            profile_type = token.payload.get("profile_type", None)
            # 给用户实例添加profile和profile_type属性
            user.profile = User.get_profile(profile_type, user)
            user.profile_type = profile_type
        
        return user, token

步骤2:替换DRF默认认证类

修改settings.py中的REST_FRAMEWORK配置,将默认的JWT认证类替换为自定义类:

REST_FRAMEWORK = {
    "DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.IsAuthenticated",),
    "DEFAULT_RENDERER_CLASSES": (
        "rest_framework.renderers.JSONRenderer",
        "rest_framework.renderers.BrowsableAPIRenderer",
    ),
    "DEFAULT_AUTHENTICATION_CLASSES": [
        "users.authentication.CustomJWTAuthentication",  # 替换为自定义类
    ],
}

步骤3:移除原Middleware(可选)

现在不需要原来的SetProfileMiddleware了,可以从settings.py的MIDDLEWARE中移除它,避免重复认证操作。

验证

修改后,视图中直接访问self.request.user.profile就能正常获取到对应的profile对象,不会再触发AttributeError。


内容的提问来源于stack exchange,提问作者Ravexina

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 22:05:57