在Django(Python)序列化器中分组任务日程数据的实现方法
解决方案:在Django Serializer中重组任务周数据结构
嗨,这个需求本质上就是按week_number对任务进行分组聚合,在Django Rest Framework(DRF)的Serializer里,我们可以通过SerializerMethodField来实现这个自定义的数据结构,下面给你两种实用的实现方案:
方案一:手动字典分组(直观易理解)
这种方式逻辑清晰,适合刚接触DRF的开发者,步骤如下:
1. 定义任务子Serializer
先写一个负责序列化单个任务条目的子Serializer,确保输出的任务格式符合要求:
from rest_framework import serializers class TaskItemSerializer(serializers.Serializer): id = serializers.IntegerField() task = serializers.IntegerField()
2. 主Serializer中实现分组逻辑
在主Serializer里用SerializerMethodField来生成目标的weeks字段,核心是用字典按周号分组任务:
class MainSerializer(serializers.Serializer): weeks = serializers.SerializerMethodField() def get_weeks(self, obj): # 从序列化对象中获取原始的周任务数据 # 如果是模型实例,改成obj.week_task_schedule.all()即可 week_tasks = obj.get('week_task_schedule', []) # 初始化字典用于分组:键为week_number,值为对应任务列表 grouped_tasks = {} for item in week_tasks: week_num = item['week_number'] # 若当前周号不在分组字典中,先创建空列表 if week_num not in grouped_tasks: grouped_tasks[week_num] = [] # 将当前任务添加到对应周的列表 grouped_tasks[week_num].append({ 'id': item['id'], 'task': item['task'] }) # 将分组后的字典转换为目标列表格式,并按周号排序 sorted_weeks = sorted(grouped_tasks.items(), key=lambda x: x[0]) return [ { 'week_number': week_num, 'tasks': TaskItemSerializer(tasks, many=True).data } for week_num, tasks in sorted_weeks ]
方案二:使用itertools.groupby(简洁高效)
如果你喜欢更简洁的写法,可以用Python标准库的itertools.groupby,但要注意必须先对原始数据按week_number排序,否则分组会失效:
from rest_framework import serializers from itertools import groupby class TaskItemSerializer(serializers.Serializer): id = serializers.IntegerField() task = serializers.IntegerField() class MainSerializer(serializers.Serializer): weeks = serializers.SerializerMethodField() def get_weeks(self, obj): week_tasks = obj.get('week_task_schedule', []) # 关键:先按week_number排序,确保groupby能正确分组 sorted_tasks = sorted(week_tasks, key=lambda x: x['week_number']) # 按week_number分组 week_groups = groupby(sorted_tasks, key=lambda x: x['week_number']) # 转换为目标格式 return [ { 'week_number': week_num, 'tasks': TaskItemSerializer(list(task_group), many=True).data } for week_num, task_group in week_groups ]
注意事项
- 如果你的数据来自Django模型实例(而非字典),只需要将
obj.get('week_task_schedule', [])替换为模型的关联字段查询,比如obj.week_task_schedule.all(),同时遍历的时候访问模型属性(如item.week_number、item.id)即可。 - 两种方案都会输出按周号从小到大排序的结果,符合你给出的目标结构要求。
内容的提问来源于stack exchange,提问作者Luís Melo
相关产品推荐
相关产品推荐

