如何在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
相关产品推荐
相关产品推荐

