异常模块

异常模块(重点)

重写异常模块目的是记录异常信息(项目上线)

1、在settings的drf配置中配置EXCEPTION_HANDLER,指向自定义的exception_handler函数

2、异常模块:django项目的所有异常都会被处理,drf能处理的会自己处理(4xx),不能处理的交给django处理(5xx)改写exception_handler,在全局配置

2、drf出现异常了,都会回调exception_handler函数,携带 异常对象和异常相关信息内容,在exception_handler函数完成异常信息的返回以及异常信息的logging日志

核心:异常信息都需要被logging记录,所以需要自定义;drf只处理客户端异常,服务器异常需要手动处理,统一处理结果

用法

  1. 主要是用来记录系统的错误,方便进行修改,特别重要,出现异常就要进行记录。
  2. 重写异常

配置settings.py

REST_FRAMEWORK = {
    # 异常
    # 'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler',#系统异常
    'EXCEPTION_HANDLER': 'api.utils.exception_handler',#重写异常

}
#测试
from rest_framework.response import Response
def exception_handler(exc, condent):
    print(exc)#错误信息
    print(condent)#错误来源
    return Response({
        'msg':"异常"
    })

初级版

from rest_framework.response import Response

def exception_handler(exc, context):
    # 开发阶段一定要记录日志
    # logging.error(exc)
    return Response('%s - %s' % (context['view'].__class__.__name__, exc))

升级版

from rest_framework.response import Response
from rest_framework.views import exception_handler as drf_exception_handler
def exception_handler(exc, context):
    response = drf_exception_handler(exc, context)

    if response is None: # drf没有处理的异常
        response = Response({'detail': '%s' % exc})

    # 项目阶段,要记录到日志文件
    return response

究极版

"""
返回数据类型
response = {
    'status': 7,
    'exc': '异常信息'
}
"""
from rest_framework.response import Response
from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework import status
def exception_handler(exc, context):
    response = drf_exception_handler(exc, context)

    if response is None: # drf没有处理的异常(服务器异常)
        return Response(status=status.HTTP_500_INTERNAL_SERVER_ERROR, data={
            'status': 7,
            'exc': '%s' % exc
        })
#设置状态码
    # 项目阶段,要记录到日志文件
    return Response(status=response.status_code, data={
        'status': 7,
        # drf处理的客户端异常,原始处理方式是将异常信息放在response对象的data中,data的格式是{'datail': '具体的异常信息'}
        'exc': '%s' % response.data.get('detail')
    })

在使用drf的时候,验证与is_valid(raise_exception=True)冲突,因此使用

from rest_framework.views import exception_handler as drf_exception_handler
from rest_framework.response import Response
def exception_handler(exc, context):
    # drf_exception_handler的执行结果就是异常信息的Response对象或None
    # 是Response对象可以直接返回
    # 是None可以从exc中拿到异常信息,从context拿到是谁出现的异常,自己格式化成Response对象返回
    # 重点:自定义异常模块目的是记录异常信息到日志文件 - 产品阶段
    response = drf_exception_handler(exc, context)
    if response is None:
        response = Response({'detail': '%s' % exc}, status=500, exception=True)
    # logging.error(response.data)
    return response

源码分析

1、在APIView的dispatch方法中,有一个超大的try...except...,将代码运行异常都交给异常处理模块处理self.handle_exception(exc)
2、从配置中映射出配置处理异常的函数(自定义异常模块就是自定义配置指向自己的函数):self.get_exception_handler()
3、异常函数exception_handler(exc, context)处理异常,就会走自己的:
先交给系统处理(客户端的异常),系统没处理(服务器异常),再自己处理

原文地址:https://www.cnblogs.com/SkyOceanchen/p/11895477.html