Django DRF嵌套序列化器POST请求时id字段丢失如何解决
问题根因
Django REST Framework的ModelSerializer默认会将模型自带的自增主键id设置为隐式只读字段,即使你没有在序列化器字段中显式标注read_only=True,该字段也不会被纳入可写字段范围,校验后自然不会出现在validated_data中。
解决方法
方法一:显式指定id为可写字段(适配需要嵌套传参的场景)
在GradeClassSerializer中手动声明id字段,覆盖默认的只读规则即可:
class GradeClassSerializer(CountryFieldMixin, serializers.ModelSerializer): """GradeClass Serializer.""" # 显式声明id为可写字段,如果需要校验id对应实例存在,可加queryset参数 id = serializers.IntegerField() class Meta: model = ClassGrade fields = ('id', 'grade', 'country', 'color_code', )
如果需要自动校验传入的id对应ClassGrade实例真实存在,可将字段声明修改为:
id = serializers.PrimaryKeyRelatedField(queryset=ClassGrade.objects.all())
修改完成后重新发送请求,validated_data['grade_level']中就可以正常获取到id字段。
方法二:优化外键关联逻辑(更符合DRF规范的推荐方案)
如果你的业务是创建Post时关联已经存在的ClassGrade实例,而非新增ClassGrade数据,完全不需要使用嵌套序列化做写入,直接用主键关联更简洁:
class PostSerializer(serializers.ModelSerializer): """Post Serializer""" owner = UserProfile(read_only=True) tags = TagSerializer(many=True) comments = CommentSerializer(many=True, read_only=True) slug = serializers.SlugField(read_only=True) # 替换原有的嵌套序列化器声明 grade_level = serializers.PrimaryKeyRelatedField(queryset=ClassGrade.objects.all()) # 配置返回响应时依然返回grade_level的完整嵌套信息 def to_representation(self, instance): data = super().to_representation(instance) data['grade_level'] = GradeClassSerializer(instance.grade_level).data return data
这种方案不需要额外处理嵌套序列化的写入逻辑,也避免了id丢失的问题。
内容的提问来源于stack exchange,提问作者Lutaaya Huzaifah Idris
相关产品推荐
相关产品推荐

