Django自定义全局异常类

Django自定义全局异常类

Django中通过继承django.utils.deprecation.MiddlewareMixin中间件来自定义类。


中间件逻辑

Django自定义全局异常类_第1张图片

由请求到逐个中间件运行,在逐个返回。


中间件方法

  • process_request(self, request):在每个request在被决定使用哪个view之前调用,它会返回None或HttpResponse对象。

  • process_exception(self, request, exception):exception是view函数中raise的Exception对象,当 view 函数 raise 一个 exception 的时候调用process_exception,它会返回None或HttpResponse对象

  • process_response(self, request, response):response 是一个django view或者中间件返回的 HttpResponse 或者StreamingHttpResponse对象,process_response会在所有响应到达浏览器之前被调用。


自定义中间件

class ExceptionMiddleware(MiddlewareMixin):
    def process_exception(self, request, exception):
        # 视图函数发生异常时调用
        if isinstance(exception, urllib.error.HTTPError):
            return JsonResponse(get_response('INPUTIMGERRPR', request, exception), status=500)
        else:
            return JsonResponse(get_response('ERROR', request, exception), status=500)

自定义ExceptionMiddleware类,继承Django中间件。

定义process_exception捕捉异常。

在异常中查看异常类别,通过类别去枚举类里映射返回信息,通过JsonResponse返回。

要在settings.py的中间件中设置自定义中间件

MIDDLEWARE = [
    .......
    'utils.exception_utils.ExceptionMiddleware'
]

自定义枚举类构造返回状态

我用枚举类做的事自定义接口返回数据,也就一个code一个message,没啥太多玩意,下面代码就搞定。虽然研究了半天,可能是我菜逼。

from enum import Enum, unique


@unique
class ResponseEntity(Enum):
    SUCCESS = (200, "执行成功")
    INPUTIMGERRPR = ('FE001', "输入图片有误")
    ERROR = (500, "程序内部错误")

    @property
    def status(self):
        """获取状态码"""
        return self.value[0]

    @property
    def msg(self):
        """获取状态码信息"""
        return self.value[1]

读取的时候也在这个py里定义了个读取的方法:

def get_response(status, requset, exception):
    resp = {
        # 时间
        'timestamp':  time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),
        # 状态码
        'errorCode': ResponseEntity[status].status,
        # 错误属性
        'errors': ResponseEntity[status].msg,
        # 异常类名属性
        'exception': type(exception).__module__ + '.' + type(exception).__name__,
        # 堆栈跟踪属性
        'trace': traceback.format_exc(),
        # 消息内容
        'message': ResponseEntity[status].msg,
        # 接口路径
        'path': requset.path
    }
    return resp

这样接口的输出就是

JsonResponse(get_response('INPUTIMGERRPR', request, exception), status=500)

再说一下__module__是python自带的魔法属性,表示当前操作的对象在哪个模块。__name__是python的一个内置类属性,获取类名。不知道有哪些内置属性可以dir()去找一下。


自定义异常类

class NoFaceException(Exception):
    def __str__(self):
        pass

写了一个检测不到人脸的异常类,继承Exception类,复写__str__(self)方法。

由于我这边统一交给枚举类处理异常信息了,这边就写个形式即可。

使用的时候

if result is None:
    raise NoFaceException

Django捕捉到异常后,会执行ExceptionMiddleware类。在类里判断是不是NoFaceException。

elif isinstance(exception, NoFaceException):
    return JsonResponse(get_response('NOFACEERROR', request, exception), status=500)

然后调用枚举类的py里写的静态方法get_response,根据NOFACEERROR拿到错误信息

NOFACEERROR = ('FE002', "输入图片没有人脸")

你可能感兴趣的:(django,python,后端)