Django API返回空Days列表问题排查:无法获取完整嵌套训练数据
问题分析与解决方案
核心问题原因
- 多对多关系创建逻辑错误:你的序列化器
create方法中,尝试通过Dia.objects.create(rutina=rutina, **dia_data)和Ejercicio.objects.create(dia=dia, **ejercicio_data)直接关联多对多关系,但你的模型中并没有对应的外键字段(Rutina与Dia、Dia与Ejercicio都是多对多关联),这导致关联关系并未正确存入数据库,查询自然拿不到数据。 - 未预加载关联数据:即使关联关系正确,DRF默认不会自动获取多对多的嵌套关联数据,需要显式通过
prefetch_related预加载,否则序列化时会返回空列表。
修复步骤
1. 修正序列化器的create方法
修改RutinaSerializer中的create方法,正确处理多对多关系的关联:
class RutinaSerializer(serializers.ModelSerializer): dias = DiaSerializer(many=True) class Meta: model = Rutina fields = ("id", "nombre", "dias") def create(self, validated_data): dias_data = validated_data.pop("dias") rutina = Rutina.objects.create(**validated_data) for dia_data in dias_data: ejercicios_data = dia_data.pop("ejercicios") # 先创建Dia对象,不直接关联Rutina dia = Dia.objects.create(**dia_data) # 通过多对多关系的add方法关联Rutina和Dia rutina.dias.add(dia) # 批量创建Ejercicio并关联到Dia ejercicios = [Ejercicio.objects.create(**data) for data in ejercicios_data] dia.ejercicios.add(*ejercicios) return rutina
2. 预加载关联数据优化查询
在视图中使用prefetch_related一次性加载所有层级的关联数据,避免N+1查询,同时确保序列化器能获取完整嵌套结构:
修改rutina_list视图:
@api_view(["GET"]) def rutina_list(request): # 预加载rutina的dias,以及每个dia的ejercicios rutinas = Rutina.objects.all().prefetch_related('dias__ejercicios') serializer = RutinaSerializer(rutinas, many=True) return Response(serializer.data)
修改RutinaViewSet:
class RutinaViewSet(viewsets.ModelViewSet): # 同样添加prefetch_related queryset = Rutina.objects.all().prefetch_related('dias__ejercicios') serializer_class = RutinaSerializer
验证效果
完成上述修改后,重新创建测试数据,调用rutina_list接口或RutinaViewSet的列表接口,即可返回包含完整嵌套结构的训练计划数据:每个Rutina包含对应的Dia列表,每个Dia包含对应的Ejercicio列表及所有动作详情。
额外说明
你手动实现的rutinas_json视图能返回正确数据,是因为它通过循环触发了关联数据的查询,但这种方式会产生大量重复数据库请求(N+1问题),性能远不如使用DRF序列化器结合prefetch_related的方案。
内容的提问来源于stack exchange,提问作者Aris
相关产品推荐
相关产品推荐

