You need to enable JavaScript to run this app. 如何在Django REST Framework序列化器中设置动态键属性?
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django REST Framework序列化器中设置动态键属性?

动态键结构的DRF序列化器实现方案

核心场景:你遇到的daySchedules是键为动态随机生成ID、值结构完全固定的字典对象,DRF没有内置字段直接适配这类场景,同时还要满足严格校验每个值的类型、结构的要求,具体实现分三步:

1. 先修正固定结构序列化器的字段映射

原始JSON的字段是驼峰命名,和你定义的蛇形字段不匹配,需要通过source指定映射关系,同时把模糊的ListField细化为明确的子序列化规则,满足你“明确指定每个属性类型”的要求:

# 定义服务时段的明确结构校验规则
class ServiceItemSerializer(serializers.Serializer):
    name = serializers.CharField()
    hours = serializers.DictField(child=serializers.CharField())
    overnight = serializers.BooleanField()

class ScheduleForDaySerializer(serializers.Serializer):
    schedule_name = serializers.CharField(source="scheduleName")
    services = serializers.ListField(child=ServiceItemSerializer())
    open_time = serializers.CharField(source="openTime")
    close_time = serializers.CharField(source="closeTime")

2. 实现动态键的DaySchedulesSerializer

因为字典的键不固定,不需要硬编码任何键名,只需要遍历所有键值对,把每个值统一用上面定义的ScheduleForDaySerializer做校验和序列化即可,完全不关心键的具体取值:

class DaySchedulesSerializer(serializers.Serializer):
    def to_internal_value(self, data):
        # 先校验入参是字典结构
        if not isinstance(data, dict):
            raise serializers.ValidationError("daySchedules必须是键值对结构")
        
        validated_data = {}
        # 逐一对每个值做严格结构校验
        for key, value in data.items():
            item = ScheduleForDaySerializer(data=value)
            if not item.is_valid():
                # 把错误信息精确对应到出错的键下面
                raise serializers.ValidationError({key: item.errors})
            validated_data[key] = item.validated_data
        return validated_data

    def to_representation(self, instance):
        ret = {}
        for key, value in instance.items():
            ret[key] = ScheduleForDaySerializer(value).data
        return ret

3. 补全最外层序列化器的字段映射

原始JSON的顶级键是驼峰结构,同样需要通过source指定和你定义的蛇形字段的对应关系,避免取不到值:

class WeekScheduleSerializer(serializers.Serializer):
    monday = serializers.CharField(allow_null=True, required=False)
    tuesday = serializers.CharField(allow_null=True, required=False)
    wednesday = serializers.CharField(allow_null=True, required=False)
    thursday = serializers.CharField(allow_null=True, required=False)
    friday = serializers.CharField(allow_null=True, required=False)
    saturday = serializers.CharField(allow_null=True, required=False)
    sunday = serializers.CharField(allow_null=True, required=False)

class SchedulesSerializer(serializers.Serializer):
    day_schedules = DaySchedulesSerializer(source="daySchedules")
    week_schedule = WeekScheduleSerializer(source="weekSchedule")

使用方式

和你预期的调用逻辑完全一致,不需要做额外修改:

serializer = SchedulesSerializer(data=data)
serializer.is_valid(raise_exception=True)
# validated_data是经过严格校验、字段名标准化后的规整结构,原始的动态ID键会完整保留
response = serializer.data

注意事项

  • 如果需要对动态键本身做格式校验(比如要求键是纯数字、固定长度),只需要在上面to_internal_value的遍历循环里,加一层对key的格式判断即可,校验不通过直接抛错。
  • 不要直接用默认DictField实现这类结构:默认DictField只会校验值是基础JSON类型,不会做深层次的结构校验,达不到你要的严格类型约束的要求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.06 14:06:07