exceptions.py 3.05 KB
import logging
import six
from django.core.exceptions import PermissionDenied
from django.utils.translation import ugettext_lazy as _
from django.http import Http404
from rest_framework import exceptions, status
from rest_framework.exceptions import NotAuthenticated, PermissionDenied
from rest_framework.response import Response
from marshmallow.exceptions import ValidationError

from .response import MetaStatus, res_content, APIResponse

error_logger = logging.getLogger('exception')


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

    By default we handle the REST framework `APIException`, and also
    Django's built-in `Http404` and `PermissionDenied`

    Any unhandled exceptions may return `None`, which will cause a 500 error
    to be raised.
    """
    if isinstance(exc, exceptions.APIException):
        headers = {}
        if getattr(exc, 'auth_header', None):
            headers['WWW-Authenticate'] = exc.auth_header
        if getattr(exc, 'wait', None):
            headers['Retry-After'] = '%d' % exc.wait

        if isinstance(exc, NotAuthenticated) or isinstance(exc, PermissionDenied):
            data = res_content(MetaStatus.NO_PERMISSION.value, MetaStatus.NO_PERMISSION.verbose_name)
        elif exc.status_code == 403:
            data = res_content(MetaStatus.NEED_LOGIN.value, MetaStatus.NEED_LOGIN.verbose_name)
        else:
            data = res_content(MetaStatus.INTERNAL_ERROR.value, exc.detail)

        return Response(data, status=200, headers=headers)

    elif isinstance(exc, Http404):
        msg = _('Not found.')
        data = {'detail': six.text_type(msg)}

        return Response(data, status=status.HTTP_404_NOT_FOUND)

    elif isinstance(exc, PermissionDenied):
        msg = _('Permission denied.')
        data = {'detail': six.text_type(msg)}

        return Response(data, status=status.HTTP_403_FORBIDDEN)

    elif isinstance(exc, ValidationError):
        meta_status = MetaStatus.INVALID_PARAMS.value
        # msg = MetaStatus.INVALID_PARAMS.verbose_name
        return APIResponse(meta_status, msg=str(exc))

    elif isinstance(exc, Exception) and hasattr(exc, 'API_META_STATUS'):
        # msg = exc.API_META_STATUS.verbose_name
        return APIResponse(exc.API_META_STATUS.value, msg=str(exc))

    error_logger.exception('[system error]')
    return APIResponse(MetaStatus.INTERNAL_ERROR.value,
                       msg=MetaStatus.INTERNAL_ERROR.verbose_name)


class NeedLoginException(Exception):
    API_META_STATUS = MetaStatus.NEED_LOGIN


class InvalidParamsException(Exception):
    API_META_STATUS = MetaStatus.INVALID_PARAMS


class InternalErrorException(Exception):
    API_META_STATUS = MetaStatus.INTERNAL_ERROR


class ObjectNotExitException(Exception):
    API_META_STATUS = MetaStatus.NOT_EXIST


class AsyncWaitException(Exception):
    API_META_STATUS = MetaStatus.ASYNC_WAIT


class NoPermissionException(Exception):
    API_META_STATUS = MetaStatus.NO_PERMISSION


class IllegalOperationException(Exception):
    API_META_STATUS = MetaStatus.ILLEGAL_OPERATION