DRF使用普通Serializer时validated_data字段被source值替换问题求解
问题原因
该问题由两处配置错误导致:
ProgramSerializer中的rules字段设置了source='priority_set',DRF反序列化时会将验证后的参数自动存入source指定的priority_set键中,导致validated_data中没有rules字段PrioritySerializer中的rule_id设置了source='rule.id',反序列化时会将入参的rule_id转换为嵌套的{'rule': {'id': xx}}结构,不符合预期
修改方案
第一步:调整PrioritySerializer区分读写字段
设置字段读写权限,反序列化时仅接收rule_id,避免生成嵌套结构:
class PrioritySerializer(serializers.Serializer): # 反序列化写入专用字段 rule_id = serializers.IntegerField(write_only=True) # 序列化输出专用字段,只读模式不参与反序列化 rule_name = serializers.CharField(source='rule.name', read_only=True) rule_rule = serializers.CharField(source='rule.rule', read_only=True) priority = serializers.IntegerField(read_only=True)
第二步:修改ProgramSerializer拆分序列化/反序列化逻辑
移除rules字段的source配置,新增to_representation方法兼容原有GET请求的返回结构,同时修正id字段为只读(创建程序无需传入ID):
class ProgramSerializer(serializers.Serializer): # 设为只读,创建资源时不需要传入 id = serializers.IntegerField(read_only=True) name = serializers.CharField(max_length=32) description = serializers.CharField(style={'base_template': 'textarea.html'}, allow_blank=True) # 移除source配置,反序列化时参数直接存入validated_data的rules键 rules = PrioritySerializer(many=True) # 重写序列化逻辑,保证GET请求返回和原有结构完全一致的规则列表 def to_representation(self, instance): rep = super().to_representation(instance) rep['rules'] = PrioritySerializer(instance.priority_set.order_by('priority').all(), many=True).data return rep def create(self, validated_data): rules_data = validated_data.pop('rules') program_obj = Program.objects.create(**validated_data) priority = 0 for rule in rules_data: # 现在rules_data是标准字典列表,直接取rule_id即可 rule_obj = Rule.objects.get(pk=rule['rule_id']) priority += 1 Priority.objects.create(program=program_obj, rule=rule_obj, priority=priority) return program_obj
可选优化:调整视图POST逻辑
创建资源时不需要partial=True参数(该参数仅用于部分更新场景),可移除:
def post(self, request, format=None): serializer = ProgramSerializer(data=request.data) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
修改完成后,validated_data的结构就和预期完全一致,且GET请求的返回结果和原有逻辑没有差异。
内容的提问来源于stack exchange,提问作者Mahalingam Sundararaj
相关产品推荐
相关产品推荐

