drf 异常捕获
2020-11-01 22:25
1041 查看
异常捕获
使用
drf进行前后端分离时,有的时候当后端出现异常,返回的数据格式并不是
JSON,你可能会发现下面这样的情况:
它会返回给你一个
HTML文档,这显然对于前端开发工程师来说是非常不友好的。
所以我们通常会将这种情况给他处理掉,学习如何处理之前要看
drf是如何对异常进行处理的。
源码阅读
首先
APIView中的
dispatch()方法中有关于异常的捕获,它的异常捕获是从执行认证开始,直到封装返回对象结束。代码如下:
def dispatch(self, request, *args, **kwargs): self.args = args self.kwargs = kwargs request = self.initialize_request(request, *args, **kwargs) self.request = request self.headers = self.default_response_headers # deprecate? try: # 异常捕获开始 self.initial(request, *args, **kwargs) if request.method.lower() in self.http_method_names: handler = getattr(self, request.method.lower(), self.http_method_not_allowed) else: handler = self.http_method_not_allowed response = handler(request, *args, **kwargs) except Exception as exc: response = self.handle_exception(exc) # 如果发生异常,则执行这里 self.response = self.finalize_response(request, response, *args, **kwargs) return self.response
在
self.handle_exception()这个方法中,你可以看到如下代码:
def handle_exception(self, exc): if isinstance(exc, (exceptions.NotAuthenticated, exceptions.AuthenticationFailed)): # 判断这个异常是不是属于AuthenticationFailed这个异常,是它就会默认给你处理好 auth_header = self.get_authenticate_header(self.request) if auth_header: exc.auth_header = auth_header else: exc.status_code = status.HTTP_403_FORBIDDEN exception_handler = self.get_exception_handler() context = self.get_exception_handler_context() response = exception_handler(exc, context) # 核心代码就在这里,它会返回这个异常的种类 return self.settings.EXCEPTION_HANDLER。 你可以导入 from rest_framework.views import exception_handler 来看看它到底是怎么处理的 if response is None: # 如果这个种类是None时,drf将不再处理这个异常,而是交由Django进行处理,所以你会看见返回大黄页 self.raise_uncaught_exception(exc) response.exception = True return response
它的处理如下:
def exception_handler(exc, context): if isinstance(exc, Http404): exc = exceptions.NotFound() elif isinstance(exc, PermissionDenied): exc = exceptions.PermissionDenied() 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.detail, (list, dict)): data = exc.detail else: data = {'detail': exc.detail} set_rollback() return Response(data, status=exc.status_code, headers=headers) # ===========以上都是drf能够去处理的异常 return None
自定异常
ok,既然它会将
drf没有处理的异常丢给原生
Django然后返回大黄页,那么能不能让
drf丢给我们写的程序来进行处理呢?
答案是肯定的。你只需要在全局做一下设置就好了,演示开始。
全局配置
首先我们要让发生异常时,第一步就是来运行我们的异常捕获程序,所以要在全局的
settings.py中做配置:
from rest_framework.settings import DEFAULTS REST_FRAMEWORK = { 'EXCEPTION_HANDLER': "app01.aberrant.exception_catch" }
书写异常
如果发生
drf无法捕获的异常,就由我们来处理,直接返回未知错误以及错误详情即可。
from rest_framework.views import exception_handler from rest_framework.response import Response from rest_framework import status def exception_catch(exc,context): # 首先我们做一个切面,拦截掉result。如果它是None则代表会返回大黄页,我们来处理 result = exception_handler(exc,context) if not result: # 如果是None,返回未知错误和错误详情,并且返回服务无法使用的状态码 return Response(data="unkown mistake, details:%s"%(str(exc)),status=status.HTTP_503_SERVICE_UNAVAILABLE) return result
下面我们自己造了一个异常,发现了它返回的不是大黄页了:
class BookAPI(ListAPIView): queryset = Book.objects.all() serializer_class = BookModelSerializers filter_backends = [BookModelSerializers] # 过滤时放入的是一个序列器,当然会抛出异常 # 返回结果 "unkown mistake, details:'BookModelSerializers' object has no attribute 'filter_queryset'"
相关文章推荐
- Application-Level层级异常捕获并定位程序的异常位置
- spring事物异常回滚,捕获异常不抛出就不会回滚
- C# winform 捕获全局异常
- 在ASP.NET中使用SOAP Extensions捕获WebService异常
- Android自定义捕获异常
- 设计捕获两种不同类型的异常,一个是被0 除,另一个是数组越界。
- Android全局异常捕获日志打印
- Android CrashHandler编写自己的异常捕获的方法
- Method.invoke 异常捕获
- 捕获线程中的异常
- 详解Android全局异常的捕获处理
- Hook线程以及捕获线程执行时的异常
- 异常捕获和log4net使用
- 关于Java的异常捕获
- iOS捕获异常,常用的异常处理方法
- springBoot系列教程07:异常捕获
- 浅析lua异常捕获处理机制
- php中try catch捕获异常实例详解
- Net 下未捕获异常的处理 (无法预料的异常处理)
- c++ 捕获所有异常