def exception_handler(exc, context=None):
    """
    Returns the response that should be used for any given exception.

    By default we handle the REST framework `APIException` and Django's builtin
    `Http404` exceptions.

    Any unhandled exceptions are caught and logged by this handler and
    an `OperationException` is raised accordingly the view or process behind
    that triggered the actual error.
    """

    if isinstance(exc, Http404):
        exc = NotFound()
    elif isinstance(exc, ValidationError):
        exc = InvalidInputException(errors=exc.detail)

    # Make sure we always working with an APIException
    if not isinstance(exc, (APIException, BaseException)):
        raise exc

    identifier = getattr(exc, "identifier", None)
    code = getattr(exc, "code", "")
    message = getattr(exc, "message", "")
    error_code = getattr(exc, "error_code", "")
    errors = getattr(exc, "errors", [])

    if not code and isinstance(exc, APIException):
        # DRF 3.5 exceptions have a proper code we can expose
        if hasattr(exc, "get_codes"):
            codes = exc.get_codes()

            if isinstance(codes, string_types):
                code = codes
            else:
                code = next(iter(codes))

        # Fallback to the default OPERATION_FAILED message
        # if also no default_code was provided
        code = code or getattr(exc, "default_code", "OPERATION_FAILED")
        code = code.upper()

    if isinstance(exc, MethodNotAllowed):
        code = "NOT_ALLOWED"
    elif isinstance(exc, NotFound):
        code = "NOT_FOUND"

    data = dict(message=message,
                errors=errors,
                key=identifier,
                code=code,
                error_code=error_code)

    return Response(data, status=exc.status_code)
Example #2
0
def custom_exception_handler(exc, context):
    """捕获rest framework 错误异常,返回自定义的错误格式"""
    if isinstance(exc, Http404):
        exc = NotFound()
    elif isinstance(exc, HttpResponseForbidden):
        exc = PermissionDenied()
    response = exception_handler(exc=exc, context=context)
    if response and isinstance(response.data, dict):
        detail = response.data.pop('detail', None)
        if detail:
            response.data['error'] = detail
        if hasattr(exc, 'get_codes'):
            response.data['code'] = exc.get_codes()
    return response