Django Rest Framework中ModelViewSet传user到Serializer报字段必填错误如何解决
错误根因
DRF 的序列化器参数校验逻辑执行在 perform_create 方法之前,你在 CommentSerializer 中将 user 字段设置为 required=True,接口收到 POST 请求时会先校验请求参数是否携带 user 字段,没携带就会直接返回你遇到的必填错误,根本不会执行到你手动赋值 user 的 perform_create 逻辑。
同时你使用嵌套的 UserSerializer 作为 user 字段的序列化类,嵌套序列化器默认仅支持读操作,就算请求携带了 user 参数也无法直接用于创建数据,不符合你的需求。
修改方案
第一步:修改序列化器配置
调整 serializer.py 中的 CommentSerializer,将 user 字段设置为只读,取消请求传参要求:
class CommentSerializer(serializers.ModelSerializer): id = serializers.CharField(read_only=True, required=False) # 把原来的required=True改成read_only=True即可 user = UserSerializer(read_only=True) text = serializers.CharField(required=True) created = serializers.DateTimeField(read_only=True) object_id = serializers.CharField(required=False) class Meta: model = Comment fields = ('id', 'user', 'text', 'created', 'object_id') read_only_fields = ('id', 'created')
第二步:完善视图创建逻辑
Comment 模型的 content_type 也是必填字段,需要从 URL 参数中提取对应值完成赋值,调整 views.py 中的 perform_create 方法:
from django.contrib.contenttypes.models import ContentType from rest_framework import viewsets from rest_framework import permissions from .models import Comment from .serializers import CommentSerializer class CommentViewSet(viewsets.ModelViewSet): queryset = Comment.objects.all() serializer_class = CommentSerializer permission_classes = [permissions.IsAuthenticated] def get_queryset(self): return self.queryset.filter(object_id=self.kwargs['object_id']) def perform_create(self, serializer): # 从URL参数获取content_type对应的实例 content_type = ContentType.objects.get(model=self.kwargs['content_type']) serializer.save( user=self.request.user, content_type=content_type, object_id=self.kwargs['object_id'] )
修改完成后,POST 请求仅需要携带 text 参数即可完成评论创建,user、content_type、object_id 均由后端自动赋值,接口会正常返回嵌套的用户信息。
内容的提问来源于stack exchange,提问作者Joe F.
相关产品推荐
相关产品推荐

