防止自定义渲染器在 Django Rest Framework 中渲染异常

问题描述 投票:0回答:1

我编写了一个自定义渲染器,允许将嵌套的 json 数据渲染为平面 Excel 文件。

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):

        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()

        # Use a temp filename to keep pandas happy.
        writer = pd.ExcelWriter(output, engine='xlsxwriter')

        # Write the data frame to the StringIO object.
        df.to_excel(writer, sheet_name='Sheet1', index=False)
        writer.save()
        data = output.getvalue()

        #Enable direct download.
        renderer_context['response']["content-disposition"] = f"attachment; filename=vodepro_export_{query_params}.xlsx"

        return data

只要在渲染之前的过程中没有异常(例如

ValidationError
),这就会按预期工作。当出现 ValidationError 时,我的自定义渲染器会尝试渲染它(但失败了,因为这甚至不是渲染器的设计行为)。

我想实现一个渲染器,它不会尝试将 ValidationErrors(或任何其他异常)解析为 Excel,但在这种情况下会回退到正常的 DRF 行为(json 或 BrowsableAPI 渲染器)?

python excel pandas django-rest-framework renderer
1个回答
0
投票

这里是代码的完整答案:

from rest_framework.renderers import JSONRenderer
from rest_framework.views import exception_handler


def custom_exception_handler(exc, context):
    """ Switch from PDFRenderer to JSONRenderer for exceptions """
    if context['request'].accepted_renderer.format == 'pdf':
        context['request'].accepted_renderer = JSONRenderer()
    return exception_handler(exc, context)

如果您已有自定义异常处理程序,请将其替换为上面代码段中 rest_framework.views 中的默认处理程序。

然后您需要在设置中进行设置:

REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'my_project.my_app.utils.custom_exception_handler'
}

你可以参考这个答案

© www.soinside.com 2019 - 2024. All rights reserved.