python - 如何在Django和Django Rest框架中覆盖/自定义所有服务器错误

标签 python django exception error-handling django-rest-framework

我有一个ViewSet:

...
from handlers import specific_exception_handler...
...

class SomeViewSet(GenericViewSet):
    """
    Some custom generic viewset
    """
    queryset = SomeModel.objects.all()
    serializer_class = SomeSerializer
    parser_classes = (ParserClassThatReadSpecificXML,)
    renderer_classes = (RendererClassThatConvertResponseIntoSpecificXML,)

    def get_exception_handler(self):
        return specific_exception_handler_function_that_return_specific_xml_format_error

    @action(methods=['post'], detail=False, url_path='some_url', url_name='some_url')
    def register(self, request, format=None):

        some_variable = request.data.get('some_value', None)

        if not some_variable:
            raise ValueError

        return Response(data=some_variable, content_type="text/xml; charset=shift_jis")
我有一个渲染器:
...
import xmltodict

class RendererClassThatConvertResponseIntoSpecificXML(BaseRenderer):
    media_type = 'text/xml'
    format = 'txt'
    charset = 'shift_jis'

    def render(self, data, media_type=None, renderer_context=None):
        # return data as non utf-8 xml string
        return xmltodict.unparse(data).encode("shift_jis")
我有一个自定义错误处理程序:
...
from rest_framework.views import exception_handler

def specific_exception_handler_function_that_return_specific_xml_format_error(exc, context):

    response = exception_handler(exc, context)

    if response is not None:
        status_code = response.status_code
    else:
        status_code = status.HTTP_500_INTERNAL_SERVER_ERROR

    specific_data_that_will_be_converted_into_xml_by_render = {'ERROR_STATUS': status_code}
    headers = {'Retry-After': '300'}

    return Response(data, content_type='text/xml; charset=shift_jis', status=status_code, headers=headers)
问题:
如果将引发View的raise ValueError,我会收到我的自定义XML格式的错误消息。
  • 但是如果在render中会发生一些异常,则会出现Django的标准500 Server Error消息
  • 如果我尝试在View外部访问,则会再次出现Django的标准404 Server Error消息

  • 我想随时显示我的自定义XML错误。
    我该怎么做?

    最佳答案

    好的,这里还是没有答案,所以我会尝试自己回答
    我最终是怎么做到的:

  • 更改了我的自定义错误处理程序:

  • ...
    from rest_framework.views import exception_handler
    from rest_framework import status
    from django.http import HttpResponse
    ...
    
    # ex-specific_exception_handler_function_that_return_specific_xml_format_error
    def inside_view_occurred_error_handler(exc, context):
    
        if isinstance(exc, rest_framework.exceptions.NotAuthenticated):
            # do custom action for NotAuthenticated
        elif isinstance(exc, rest_framework.exceptions.PermissionDenied):
            # do custom action for PermissionDenied
        elif ...
            # do actions for other drf errors if needed
    
        # set status (for example 500)
        status = status.HTTP_500_INTERNAL_SERVER_ERROR
        # set body
        body='<?xml version="1.0" encoding="shift_jis"?><a attr="error">エラー</a>'.encode('shift_jis')
    
        # create response
        r = HttpResponse(body, status=status, content_type='text/xml; charset=shift_jis')
    
        # add headers
        r['Retry-After'] = '3000'
    
        return r
    
    def outside_view_400_error_handler(request, exception):
    
        # set status
        status = status.HTTP_400_BAD_REQUEST
        # set body
        body='<?xml version="1.0" encoding="shift_jis"?><a attr="error_400">エラー400</a>'.encode('shift_jis')
    
        # create response
        r = HttpResponse(body, status=status, content_type='text/xml; charset=shift_jis')
    
        # add headers
        r['Retry-After'] = '3000'
    
        return r
    
    def outside_view_500_error_handler(request):
    
        # set status
        status = status.HTTP_500_INTERNAL_SERVER_ERROR
        # set body
        body='<?xml version="1.0" encoding="shift_jis"?><a attr="error_500">エラー500</a>'.encode('shift_jis')
    
        # create response
        r = HttpResponse(body, status=status, content_type='text/xml; charset=shift_jis')
    
        # add headers
        r['Retry-After'] = '3000'
    
        return r
    
    def outside_view_404_error_handler(request, exception):
    
        # set status
        status = status.HTTP_404_NOT_FOUND
        # here is no body
    
        # create response
        r = HttpResponse(status=status, content_type='text/xml; charset=shift_jis')
    
        return r
    
  • 在urls.py中添加了处理程序

  • handler400 = 'application.handlers.outside_view_400_error_handler'
    handler404 = 'application.handlers.outside_view_404_error_handler'
    handler500 = 'application.handlers.outside_view_500_error_handler'
    
    现在,如果DEBUG = False Django随时使用自定义响应进行响应。

    关于python - 如何在Django和Django Rest框架中覆盖/自定义所有服务器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62948384/

    相关文章:

    python - Google App Engine 上传失败

    python - 了解 Django 中的原子事务

    Django:无法使用预取计算属性进行注释

    python - Django:选择 JsonField 作为 new_name?

    python - 如何将 TKinter 中的 .configure 压缩为一个命令?

    Python 和 urllib2 : how to make a GET request with parameters

    django - 如何修改get_queryset结果值

    exception - 如何在 Haskell 中定义自定义异常?

    python - 在 Dart 中,Python 的 try...catch...else 最惯用的替代方法是什么?

    Windows VEH - 捕获并丢弃 SINGLE_STEP 异常