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

DRF多对多模型嵌套序列化归一化 实现XLSXRenderer导出Excel报告

解决方案

问题根因

你之前导出为空的核心原因是:查询返回的QuerySet以Books为主体,单个Books对象关联多个Authors的嵌套结构无法被XLSXRenderer自动识别并拆分为多行,且原有序列化器未定义author_name平字段,渲染器无法匹配到对应数据。

具体实现方案

我们直接使用Django ManyToMany字段自动生成的中间表作为查询主体,中间表的每一行天然对应「单本书-单个作者」的映射关系,完全匹配你需要的导出结构,效率最高。

第一步:修正原有代码笔误

先修正现有代码里的语法错误,避免运行报错:

  1. Authors模型里的class Mets改为class Meta
  2. Books模型里的related_names改为related_name
  3. 序列化器定义里的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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 22:57:01