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

如何让Django Rest Framework自定义渲染器不渲染异常?

解决DRF自定义ExcelRenderer异常时回退默认渲染行为的问题

要实现异常时回退到DRF默认的JSON/可浏览API渲染行为,你可以在自定义ExcelRenderer的render方法中先判断响应是否为异常状态(状态码4xx/5xx),如果是则直接调用DRF的默认渲染器处理异常数据,而非继续执行Excel生成逻辑。

修改后的完整代码

from rest_framework import renderers, exceptions as rest_exceptions
from rest_framework.renderers import JSONRenderer, BrowsableAPIRenderer
import io
import pandas as pd
import logging

logger = logging.getLogger(__name__)

def json_into_flat_dataframe(data):
    # 保留你的JSON扁平化逻辑
    pass

class ExcelRenderer(renderers.BaseRenderer):
    """Custom renderer for exporting XLS files"""

    media_type = "application/xlsx"
    format = "excel"
    render_style = 'binary'

    def render(self, data, accepted_media_type=None, renderer_context=None):
        renderer_context = renderer_context or {}
        response = renderer_context.get('response')

        # 检测异常响应:状态码4xx/5xx时,回退到DRF默认渲染行为
        if response is not None and response.status_code >= 400:
            # 根据客户端Accept头选择对应渲染器
            accept_header = renderer_context['request'].headers.get('Accept', '')
            if 'text/html' in accept_header:
                renderer = BrowsableAPIRenderer()
            else:
                renderer = JSONRenderer()
            return renderer.render(data, accepted_media_type, renderer_context)

        # 处理查询参数生成文件名
        query_params = renderer_context["request"].query_params
        query_params = "_".join([f"{v.split('T')[0]}" for k,v in query_params.items()])

        """
        Render `data` into XLSX workbook, returning a workbook.
        """
        try:
            df = json_into_flat_dataframe(data)
        except Exception as e:
            logger.error(e, exc_info=True)
            df = pd.DataFrame()

        if len(df.index) == 0:
            raise rest_exceptions.APIException("No data!")

        output = io.BytesIO()
        writer = pd.ExcelWriter(output, engine='xlsxwriter')
        df.to_excel(writer, sheet_name='Sheet1', index=False)
        writer.save()
        data = output.getvalue()

        # 设置下载头
        renderer_context['response']["content-disposition"] = f"attachment; filename=vodepro_export_{query_params}.xlsx"

        return data

关键修改说明

  1. 异常响应检测:在渲染逻辑最开始,通过response.status_code >= 400判断当前响应是否为异常状态(如ValidationError、APIException等都会生成4xx/5xx状态码)。
  2. 匹配默认渲染行为:根据客户端请求的Accept头,选择BrowsableAPIRenderer(可浏览API页面)或JSONRenderer(JSON格式)处理异常数据,完全对齐DRF默认的异常响应逻辑。
  3. 不影响正常流程:仅在异常场景触发回退,正常数据仍按原逻辑生成Excel文件。

内容的提问来源于stack exchange,提问作者Marjan Moderc

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 05:15:35