如何在djangorestframework-simplejwt中重写request.user为ProjectMember
解决request.user自动返回ProjectMember实例的方案
下面提供两种可落地的实现方式,避免在每个视图中重复编写转换逻辑:
方法一:重写SimpleJWT认证后端
利用simplejwt的认证流程,在获取用户后自动替换为ProjectMember实例(如果存在的话)。
- 创建自定义认证类
# 在你的app下新建authentication.py from rest_framework_simplejwt.authentication import JWTAuthentication from .models import ProjectMember class CustomJWTAuthentication(JWTAuthentication): def authenticate(self, request): # 调用父类方法完成基础JWT认证,拿到User实例和token user, token = super().authenticate(request) if user and user.is_authenticated: # 尝试获取关联的ProjectMember,不存在则保留原User实例 try: project_member = ProjectMember.objects.get(user=user) user = project_member except ProjectMember.DoesNotExist: pass return user, token
- 在settings.py中配置DRF使用自定义认证类
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [ 'your_app.authentication.CustomJWTAuthentication', # 保留其他需要的认证类 ], }
方法二:使用Django中间件
通过中间件在请求到达视图前修改request.user对象。
- 创建自定义中间件
# 在你的app下新建middleware.py from django.utils.deprecation import MiddlewareMixin from .models import ProjectMember class ProjectMemberMiddleware(MiddlewareMixin): def process_request(self, request): # 仅处理已认证的用户 if request.user.is_authenticated: try: project_member = ProjectMember.objects.get(user=request.user) request.user = project_member except ProjectMember.DoesNotExist: pass
- 在settings.py中注册中间件(注意顺序,需放在认证中间件之后)
MIDDLEWARE = [ # 其他系统中间件... 'django.contrib.auth.middleware.AuthenticationMiddleware', 'your_app.middleware.ProjectMemberMiddleware', # 其他自定义中间件... ]
关键注意事项
- 如果一个User对应多个ProjectMember,上述代码的
get()会抛出MultipleObjectsReturned异常。这种场景下,需要补充逻辑(比如从URL参数、请求头中获取当前项目ID,过滤出对应ProjectMember)。 - 建议将ProjectMember与User的关联改为
OneToOneField,避免多实例问题:
class ProjectMember(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='projectmember') project = models.ForeignKey("project.Project", on_delete=models.CASCADE)
内容的提问来源于stack exchange,提问作者egvo
相关产品推荐
相关产品推荐

