DRF多对多模型嵌套序列化归一化 实现XLSXRenderer导出Excel报告
解决方案
问题根因
你之前导出为空的核心原因是:查询返回的QuerySet以Books为主体,单个Books对象关联多个Authors的嵌套结构无法被XLSXRenderer自动识别并拆分为多行,且原有序列化器未定义author_name平字段,渲染器无法匹配到对应数据。
具体实现方案
我们直接使用Django ManyToMany字段自动生成的中间表作为查询主体,中间表的每一行天然对应「单本书-单个作者」的映射关系,完全匹配你需要的导出结构,效率最高。
第一步:修正原有代码笔误
先修正现有代码里的语法错误,避免运行报错:
Authors模型里的class Mets改为class MetaBooks模型里的related_names改为related_name- 序列化器定义里的
serializer.ModelSerializer改为serializers.ModelSerializer,field属性改为复数fields
第二步:修改序列化器(serializers.py)
新增扁平化序列化器,直接适配导出需要的两个字段:
from rest_framework import serializers from .models import Books class FlatBookExportSerializer(serializers.ModelSerializer): # 关联取book的书名、author的姓名 book_name = serializers.CharField(source="book.book_name") author_name = serializers.CharField(source="author.name") class Meta: # 直接绑定ManyToMany自动生成的中间表 model = Books.authors.through fields = ("book_name", "author_name")
第三步:修改视图(views.py)
调整查询逻辑,返回中间表的QuerySet,同时保留原有的按book_id过滤的逻辑:
class ReportViewSet(XLSXFileMixin, viewsets.ReadOnlyModelViewSet): # 替换为新的扁平化序列化器 serializer_class = FlatBookExportSerializer renderer_classes = [XLSXRenderer] filename = 'my_export.xlsx' def get_queryset(self): # 查询中间表,提前预加载关联数据避免N+1查询 queryset = Books.authors.through.objects.select_related("book", "author").all() book_id = self.request.query_params.get("pk", None) if book_id is not None: queryset = queryset.filter(book_id=book_id) return queryset
效果说明
修改后接口返回的结构完全符合你的预期,XLSXRenderer可以直接识别book_name和author_name两个平字段,导出的Excel会正常填充所有行数据,不会出现空表问题。
内容的提问来源于stack exchange,提问作者TechSavy
相关产品推荐
相关产品推荐

