drf 异常捕获

drf 异常捕获,第1张

概述异常捕获 使用drf进行前后端分离时,有的时候当后端出现异常,返回的数据格式并不是JSON,你可能会发现下面这样的情况: 它会返回给你一个HTML文档,这显然对于前端开发工程师来说是非常不友好的。 所 异常捕获

   使用drf进行前后端分离时,有的时候当后端出现异常,返回的数据格式并不是JsON,你可能会发现下面这样的情况:

  

   它会返回给你一个HTML文档,这显然对于前端开发工程师来说是非常不友好的。

   所以我们通常会将这种情况给他处理掉,学习如何处理之前要看drf是如何对异常进行处理的。

源码阅读

   首先APIVIEw中的dispatch()方法中有关于异常的捕获,它的异常捕获是从执行认证开始,直到封装返回对象结束。代码如下:

    def dispatch(self,request,*args,**kwargs):        self.args = args        self.kwargs = kwargs        request = self.initialize_request(request,**kwargs)        self.request = request        self.headers = self.default_response_headers  # deprecate?        try:  # 异常捕获开始            self.initial(request,**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,**kwargs)        except Exception as exc:            response = self.handle_exception(exc)  # 如果发生异常,则执行这里        self.response = self.finalize_response(request,response,**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 DEFAulTSREST_FRAMEWORK = {    'EXCEPTION_HANDLER': "app01.aberrant.exception_catch"}
书写异常

   如果发生drf无法捕获的异常,就由我们来处理,直接返回未知错误以及错误详情即可。

from rest_framework.vIEws import exception_handlerfrom rest_framework.response import Responsefrom rest_framework import statusdef 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'"
总结

以上是内存溢出为你收集整理的drf 异常捕获全部内容,希望文章能够帮你解决drf 异常捕获所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1214211.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-05
下一篇 2022-06-05

发表评论

登录后才能评论

评论列表(0条)

保存