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

如何在Django REST Framework中实现关联模型分组序列化?

Django REST Framework 实现层级分组序列化需求

问题描述

我定义了如下Django模型:

class schoolCycle(models.Model):
    name = models.CharField(max_length=255)
    code = models.CharField(max_length=255)

class measurements(models.Model):
    name = models.CharField(max_length=255)
    weight = models.FloatField()
    school_cycle_id = models.ForeignKey(schoolCycle,on_delete=models.DO_NOTHING, related_name='measurements')
    code = models.CharField(max_length=255)

class aspects(models.Model):
    name = models.CharField(max_length=255)
    code = models.CharField(max_length=255)
    measurement_id = models.ForeignKey(measurements,on_delete=models.DO_NOTHING, related_name='aspects')

class standards(models.Model):
    name = models.CharField(max_length=255)
    code = models.CharField(max_length=255)
    weight = models.FloatField()
    aspect_id = models.ForeignKey(aspects,on_delete =models.DO_NOTHING, related_name='standards')

模型关联关系:standards 关联 aspects,aspects 关联 measurements,measurements 关联 schoolCycle。

我需要生成如下层级分组的序列化结果:

[{ 
  "measurement 1" : { 
    "school cycle 1" :{
      "aspect 1": [
        {"standard 1" : ...},
        {"standard 2" : ...}
      ],
      "aspect 2": [
        {"standard 3" : ...},
        {"standard 4" : ...}
      ]
    },
    "school cycle 2" :{
      "aspect 3": [
        {"standard 5" : ...},
        {"standard 6" : ...}
      ],
      "aspect 4": [
        {"standard 7" : ...},
        {"standard 8" : ...}
      ]
    }
  },
  "measurement 2" : { 
    "school cycle 3" :{
      "aspect 5": [
        {"standard 9" : ...},
        {"standard 10" : ...}
      ],
      "aspect 6": [
        {"standard 11" : ...},
        {"standard 12" : ...}
      ]
    },
    "school cycle 4" :{
      "aspect 7": [
        {"standard 13" : ...},
        {"standard 14" : ...}
      ],
      "aspect 8": [
        {"standard 15" : ...},
        {"standard 16" : ...}
      ]
    }
  }
}]

即按相同的 measurement 和 schoolCycle 对 aspects 进行分组序列化,请问如何在Django REST Framework中实现?

实现方案

要实现这种自定义层级结构的序列化,可通过自定义序列化器配合视图手动组织数据结构完成,步骤如下:

1. 定义基础序列化器

先为最底层的 standards 编写序列化器,指定需要返回的字段:

from rest_framework import serializers
from .models import standards, aspects, measurements, schoolCycle

class StandardSerializer(serializers.ModelSerializer):
    class Meta:
        model = standards
        fields = ['name', 'code', 'weight']  # 按需调整返回字段

2. 视图中构建层级数据

在视图里从 measurements 开始查询,同时预加载关联模型避免重复数据库查询,然后手动遍历构建目标结构:

from rest_framework.views import APIView
from rest_framework.response import Response
from .models import measurements

class HierarchyView(APIView):
    def get(self, request):
        # 预加载关联数据,优化查询性能
        queryset = measurements.objects.select_related('school_cycle_id').prefetch_related(
            'aspects__standards'
        )
        
        result = {}
        
        for measurement in queryset:
            measurement_name = measurement.name
            school_cycle_name = measurement.school_cycle_id.name
            
            # 初始化measurement层级
            if measurement_name not in result:
                result[measurement_name] = {}
            # 初始化school cycle层级
            if school_cycle_name not in result[measurement_name]:
                result[measurement_name][school_cycle_name] = {}
            
            # 处理当前measurement下的所有aspect
            for aspect in measurement.aspects.all():
                aspect_name = aspect.name
                # 序列化aspect下的所有standards
                standard_list = StandardSerializer(aspect.standards.all(), many=True).data
                # 将标准列表存入对应aspect的键
                result[measurement_name][school_cycle_name][aspect_name] = standard_list
        
        # 按需求用列表包裹结果返回
        return Response([result])

3. 配置URL路由

将视图绑定到路由:

from django.urls import path
from .views import HierarchyView

urlpatterns = [
    path('hierarchy/', HierarchyView.as_view(), name='hierarchy'),
]

关键说明

  • 查询优化:使用 select_related 处理外键关联、prefetch_related 处理反向关联,避免N+1查询问题,提升接口性能。
  • 自定义结构:DRF默认嵌套序列化器无法直接生成以名称为键的层级结构,手动遍历组织数据是最直接的实现方式。
  • 字段灵活调整:如需修改返回字段,直接调整 StandardSerializer 的 fields 列表,或在构建数据时按需提取字段即可。

内容的提问来源于stack exchange,提问作者Gutema T Jordan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 10:31:19