You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

序列化对象列表时验证通过的对象返回为空的问题排查

问题:验证通过的序列化对象返回为空,且需实现列表对象的验证规则

相关代码

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传递:
    # ViewSet中修改Serializer初始化代码
    serializer = ResponsesSerializer(data=queryset, many=True, context={'original_data_list': queryset})
    
    随后在Serializer的validate方法中对应获取数据即可。
  • 使用many=True时,列表中的每个对象都会单独经过to_internal_value、validate和to_representation处理,确保每个对象都符合验证规则。

内容的提问来源于stack exchange,提问作者TabulaRasa

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 00:05:27