序列化对象列表时验证通过的对象返回为空的问题排查
问题:验证通过的序列化对象返回为空,且需实现列表对象的验证规则
相关代码
ViewSet中的代码
serializer = ResponsesSerializer(data=queryset, many=True) serializer.is_valid(raise_exception=True) validated_data = serializer.validated_data response = Response(validated_data, status=status.HTTP_200_OK) return response
测试用queryset
queryset = [ { "C_Ethnicity.r1": 0, "C_Ethnicity.r2": 0, "EaseOfFind.r1": 0, "EaseOfFind.r2": 1, "Leg.r1": 0, "Leg.r2": 0, "record": 17 }, { "C_Ethnicity.r1": 0, "C_Ethnicity.r2": 0, "EaseOfFind.r1": 0, "EaseOfFind.r2": 1, "Leg.r1": 1, "Leg.r2": 0, }, { "C_Ethnicity.r1": 0, "C_Ethnicity.r2": 0, "EaseOfFind.r1": 0, "EaseOfFind.r2": 1, "Leg.r1": 1, "Leg.r2": 0, } ]
响应结果
[ {}, { "non_field_errors": [ "Missing 'record' key in dictionary." ] }, { "non_field_errors": [ "Missing 'record' key in dictionary." ] } ]
当前ResponsesSerializer代码
class ResponsesSerializer(serializers.Serializer): def to_internal_value(self, data): return data def validate(self, data): if 'record' not in data: raise serializers.ValidationError("Missing 'record' key in dictionary.") return data
问题原因
第一个验证通过的对象返回为空,核心原因是你的Serializer没有定义任何字段。
Django REST Framework的Serializer默认会根据类中显式定义的字段处理序列化输出:
- 调用
serializer.validated_data或进行序列化输出时,框架仅会序列化那些在类中定义的字段; - 你的Serializer仅重写了
to_internal_value和validate方法,但未定义任何字段,因此即使验证通过,也没有可序列化的内容,最终返回空对象{}。
另外,to_internal_value仅负责输入验证环节的处理,输出序列化逻辑依旧依赖于定义的字段或重写的to_representation方法。
解决方案
要实现「验证每个对象必须包含record键/满足指定项数,同时忽略其他键」的需求,可按以下方式修改Serializer:
方案1:显式定义需保留的字段(仅保留record)
如果只需返回record字段,同时验证其存在:
class ResponsesSerializer(serializers.Serializer): record = serializers.IntegerField() # 显式定义record字段 def validate(self, data): # 额外验证项数:示例要求原始数据至少包含7个键 original_data = self.context.get('original_data') if len(original_data.keys()) < 7: raise serializers.ValidationError("Data does not have enough fields.") return data
方案2:重写to_representation自定义输出内容
如果需要保留record并忽略其他键,或自定义输出格式:
class ResponsesSerializer(serializers.Serializer): def to_internal_value(self, data): # 过滤数据,仅保留record字段 filtered_data = {'record': data.get('record')} return filtered_data def validate(self, data): if 'record' not in data or data['record'] is None: raise serializers.ValidationError("Missing 'record' key in dictionary.") # 验证项数:检查原始数据的键数量 original_data = self.context.get('original_data') if len(original_data.keys()) < 7: raise serializers.ValidationError("Data has insufficient fields.") return data def to_representation(self, instance): # 定义输出格式,仅返回record return {'record': instance['record']}
注意事项
- 若要在
validate中访问原始输入数据(比如检查项数),需在初始化Serializer时通过context传递:
随后在Serializer的# ViewSet中修改Serializer初始化代码 serializer = ResponsesSerializer(data=queryset, many=True, context={'original_data_list': queryset})validate方法中对应获取数据即可。 - 使用
many=True时,列表中的每个对象都会单独经过to_internal_value、validate和to_representation处理,确保每个对象都符合验证规则。
内容的提问来源于stack exchange,提问作者TabulaRasa
相关产品推荐
相关产品推荐

