在异常时覆盖django-rest-framework中的已接受渲染器

kat*_*lee 8 python django django-rest-framework

我正在使用django-rest-framework来创建一个返回PDF的端点.但是,当呈现PDF时出错,我想返回JSON响应.但DRF将异常数据传递给我的PDFRenderer类.只有在出现错误时,我才能使用JSONRenderer?

class PDFRenderer(BaseRenderer):
    """ DRF renderer for PDF binary content. """
    media_type = 'application/pdf'
    format = 'pdf'
    charset = None
    render_style = 'binary'

    def render(self, data, media_type=None, renderer_context=None):
        return bytes(data)
Run Code Online (Sandbox Code Playgroud)

例如,当我的视图显示时raise PermissionDenied(),由于授权用户无权查看请求的PDF,因此DRF将{'detail': 'You do not have permission to perform this action.'}作为data参数传递给PDFRenderer.render.

编辑:我尝试了一个自定义异常处理程序,但显然你仍然必须通过DRF的异常处理程序运行它,它将它传递给PDFRenderer.

kat*_*lee 5

毕竟,我找到了一种使用自定义异常处理程序来执行此操作的方法:

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)
Run Code Online (Sandbox Code Playgroud)

感觉很hacky。还是希望有更好的答案。


Mih*_*ail 5

如果请求正常并且文件存在,我将其作为字节读取并将其传递给响应,作为自定义渲染器,我使用 PDFRenderer 作为您的。如果请求不正确,我将返回 json。我的解决方案是检查数据是否是字节的实例,如果不是,我只是从有效的 json 字符串返回字节,因为渲染方法无论如何都应该返回字节

class PDFRenderer(BaseRenderer):
    media_type = 'application/pdf'
    format = 'pdf'
    charset = None
    render_style = 'binary'

    def render(self, data, media_type=None, renderer_context=None):
        if isinstance(data, bytes):
            return data
        data_to_response = json.dumps(data)
        return bytes(data_to_response.encode('utf-8'))
Run Code Online (Sandbox Code Playgroud)