如何配置Django Rest Framework在序列化器验证前自动填充登录用户字段
解决方法
你遇到的报错是因为序列化器默认user是必填可写字段,反序列化校验时会检查请求 payload 中是否存在该字段,我们可以通过两种方案解决:
方案一:使用HiddenField自动注入(最简方案)
如果不需要接口返回结果中展示用户信息,直接修改序列化器的user字段定义即可,无需改动视图代码:
# serializers.py class TaskSerializer(serializers.HyperlinkedModelSerializer): # 替换原有的user字段定义 user = serializers.HiddenField( default=serializers.CreateOnlyDefault(serializers.CurrentUserDefault()) ) class Meta: model = Task fields = ['id', 'created', 'domain', 'user']
CurrentUserDefault会自动从请求上下文里取request.user赋值CreateOnlyDefault保证该字段仅在创建实例时赋值,更新操作不会修改用户关联
方案二:设置只读字段+视图手动赋值(保留返回用户信息)
如果需要接口返回结果中仍然展示用户的email信息,用这个方案:
步骤1:修改序列化器,将user设为只读
# serializers.py class TaskSerializer(serializers.HyperlinkedModelSerializer): user = serializers.SlugRelatedField( queryset=CustomUser.objects.all(), slug_field='email', read_only=True # 新增这行,标记为只读 ) class Meta: model = Task fields = ['id', 'created', 'domain', 'user']
标记为只读的字段不会参与反序列化校验,但是序列化返回时会正常输出字段值。
步骤2:修改视图create方法,保存时注入当前用户
# views.py from rest_framework import status from rest_framework.response import Response class TaskApiViewSet(viewsets.ModelViewSet): # ... 其余原有代码保持不变 ... def create(self, request): domain = request.data['domain'] can_create_task = self.task_service.can_create_task(user=request.user, domain_name=domain) if not can_create_task: raise PermissionDenied(code=None, detail=None) # 替换原有super().create(request)逻辑,手动保存用户 serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) serializer.save(user=request.user) # 手动传入当前登录用户 headers = self.get_success_headers(serializer.data) return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
内容的提问来源于stack exchange,提问作者steelcityamir
相关产品推荐
相关产品推荐

