Title(EN): Django REST Framework Learning Notes (5): the exceptions module  
Author: dog2 
 
 
基本信息 
异常处理 
DRF异常处理 
所有经过drf的APIView视图类产生的异常,都可以提供异常处理方案 
drf默认提供了异常处理方案rest_framework.views.exception_handler,但是处理范围有限 
drf提供的处理方案两种,处理了返回异常现象,没处理返回None(后续就是服务器抛异常给前台) 
 
通常出于一些原因我们需要自定义异常处理,而非使用DRF的默认异常。
基于DRF自定义异常处理 
自定义异常处理的常见应用场景如下:
解决drf没有处理的异常 
让前台得到合理的异常信息返回、隐藏异常细节而返回通用异常信息 
后台记录异常具体信息、如将异常细节写入日志以供审计等 
 
 
源码分析 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 response = self.handle_exception(exc)   exception_handler = self.get_exception_handler()  return  self.settings.EXCEPTION_HANDLERsettings = api_settings 'EXCEPTION_HANDLER' : 'rest_framework.views.exception_handler' response = exception_handler(exc, context)    
 
从dispatch中的handle_exception进入,get_exception_handler()获得处理异常方法exception_handler(),在这里也可以自定义异常方法。执行exception_handler()获取异常处理的结果。
用法示例 
自定义全局配置 
这是视频教程里的做法,它对于所有视图都采用自己定制的异常处理函数。
在项目的settings.py中 
 
1 2 3 4 5 REST_FRAMEWORK = {          'EXCEPTION_HANDLER' : 'api.exception.exception_handler' ,   } 
 
创建自定义异常处理函数,函数内部逻辑一般为
先将异常处理交给rest_framework.views的exception_handler去处理 
判断处理的结果(返回值)response,有值代表drf已经处理了,None代表drf处理不了的异常,需要自定义去处理 
  
 
api应用下创建处理异常文件exception.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 from  rest_framework.views import  exception_handler as  drf_exception_handler   from  rest_framework.views import  Responsefrom  rest_framework import  statusdef  exception_handler (exc, context) :            response = drf_exception_handler(exc, context)          if  response is  None :                            print('%s - %s - %s'  % (context['view' ], context['request' ].method, exc))         return  Response({             'detail' : 'global customized exception: internal server error'           }, status=status.HTTP_500_INTERNAL_SERVER_ERROR, exception=True )     return  response      
 
自定义局部配置 
这是我拓展的方法,它可以针对某个特定的视图类,定制不同于全局定制异常的特有处理方式。
根据前面的源码分析中可以知道,要为视图类单独定制异常处理函数,可以这样做:
在继承APIView编写视图类时,重写父类的get_exception_handler函数,让异常处理函数指向自定义的异常处理函数。 
在视图类中加入定制的异常处理函数。 
 
示例代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 from  django.views.decorators.csrf import  csrf_exemptfrom  django.utils.decorators import  method_decoratorfrom  rest_framework.views import  exception_handler as  drf_exception_handlerfrom  rest_framework.views import  Responsefrom  rest_framework import  status@method_decorator(csrf_exempt, name='dispatch') class  LocalExceptionView (APIView) :    def  post (self, request, *args, **kwargs) :         print(request.query_params)         print(request.data)         print(request.not_exists)          return  Response('post ok' )     def  get_exception_handler (self) :         return  self.exception_handler     def  exception_handler (self, exc, context) :                  response = drf_exception_handler(exc, context)                  if  response is  None :                                        print('%s - %s - %s'  % (context['view' ], context['request' ].method, exc))             return  Response({                 'detail' : 'local customized exception: internal server error'               }, status=status.HTTP_500_INTERNAL_SERVER_ERROR, exception=True )         return  response      
 
测试demo 
测试代码在这里:no5_drf_exception 
其中包含: