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

Python DRF如何通过序列化器生成指定结构的JSON响应

DRF自定义JSON响应格式解决方案

问题根源

  1. 现有RatingsSerializer将不同机构的评级作为同一条记录的两个字段返回,不符合目标格式中「每个机构作为ratings数组独立元素」的要求
  2. 字段名未做对应映射:source需映射为review_org、report_url需映射为review_url
  3. 空值返回字符串'null',不符合预期的空数组格式
  4. 序列化方法中存在大量无意义的全表查询,性能损耗极大

修改后的序列化器代码

class CurriculumSerializer(ModelSerializer):
    grade_level = serializers.CharField(source='grade_level_dim')
    subject_abbr = serializers.CharField(source='subject_abbr_dim')
    product_id = serializers.IntegerField(source='dim_id')
    product_title = serializers.CharField(source='title_dim')
    ratings = serializers.SerializerMethodField()
    
    class Meta:
        model = Table2
        fields = [
            'grade_level',
            'subject',
            'subject_abbr',
            'product_id',
            'product_title',
            'ratings'
        ]

    def get_ratings(self,obj):
        # 直接查询当前课程对应的所有评级记录,避免全表扫描
        rating_records = Table3.objects.filter(
            title=obj.title_dim, 
            grade_level=obj.grade_level, 
            subject_abbr=obj.subject_abbr_dim,
            source__in=['Org1', 'Org2']
        )
        # 按机构分组,同一机构的记录合并为一个评级项
        rating_map = {}
        for record in rating_records:
            source = record.source
            if source not in rating_map:
                rating_map[source] = {
                    "review_org": source,
                    "review_url": record.report_url,
                    "review_items": []
                }
            # 序列化单个评级子项
            item_serializer = reportSerializer(record)
            rating_map[source]['review_items'].append(item_serializer.data)
        # 按Org1、Org2的顺序返回,没有数据的机构返回空数组
        ratings = []
        for org in ['Org1', 'Org2']:
            if org in rating_map:
                ratings.append(rating_map[org])
            else:
                ratings.append({
                    "review_org": org,
                    "review_url": "", # 无数据时可填默认值或留空
                    "review_items": []
                })
        return ratings

class reportSerializer(ModelSerializer):
    class Meta:
        model = Table3
        fields = ['name', 'value', 'label', 'label_color']

class DistrictDetailSerializer(ModelSerializer):
    curriculum = serializers.SerializerMethodField()

    class Meta:
        model = Table1
        exclude = ('finance_total', 'revenue_total')

    def get_curriculum(self, obj):
        # 查询当前主体关联的所有课程
        course_queryset = Table2.objects.filter(id=obj.id).distinct('col1','col2')
        if not course_queryset.exists():
            return {}
        serializer = CurriculumSerializer(course_queryset, many=True)
        curriculum_map = {}
        for d in serializer.data:
            key = f"{d['grade_level']} {d['subject_abbr']}"            
            if key in curriculum_map:
                curriculum_map[key].append(d)
            else:
                curriculum_map[key] = [d]
        return curriculum_map

核心修改说明

  • 重构了get_ratings方法,直接获取当前课程关联的所有评级记录,按机构分组生成数组元素,避免全表查询,性能提升明显
  • 移除了冗余的RatingsSerializer,直接手动构造符合要求的评级对象结构,完全匹配目标格式的层级
  • 空值统一返回空数组,替换原有的字符串'null',符合JSON规范
  • 字段名已按目标格式做映射调整,无需额外处理

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 07:45:04