Django(50)drf异常模块源码分析

Django(50)drf异常模块源码分析异常模块源码入口APIView类中dispatch方法中的:response=self.handle_exception(exc)源码分析我们点击handle_exception跳转,查看该

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

异常模块源码入口

APIView类中dispatch方法中的:response = self.handle_exception(exc)
 

源码分析

我们点击handle_exception跳转,查看该方法源码

def handle_exception(self, exc):
    """
    Handle any exception that occurs, by returning an appropriate response,
    or re-raising the error.
    """
    # 判断异常类型是否是没有认证的类型,最后返回403状态码
    if isinstance(exc, (exceptions.NotAuthenticated,
                        exceptions.AuthenticationFailed)):
        # WWW-Authenticate header for 401 responses, else coerce to 403
        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)
    
    # 如果响应为内容为空,则抛出异常
    if response is None:
        self.raise_uncaught_exception(exc)

    response.exception = True
    return response

以上源码最为关键的一句就在于exception_handler = self.get_exception_handler(),我们可以点击查看该方法源码

def get_exception_handler(self):
    """
    Returns the exception handler that this view uses.
    """
    return self.settings.EXCEPTION_HANDLER

该方法返回该视图的异常处理方法,从返回的内容,我们可以知道,该方法在settings文件中有个默认值,进入settings可查看到

'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler',

异常处理的默认方法就是views下的exception_handler方法,我们再进入查看该方法源码

def exception_handler(exc, context):
    """
    Returns the response that should be used for any given exception.

    By default we handle the REST framework `APIException`, and also
    Django's built-in `Http404` and `PermissionDenied` exceptions.

    Any unhandled exceptions may return `None`, which will cause a 500 error
    to be raised.
    """
    # 判断异常是否是404
    if isinstance(exc, Http404):
        exc = exceptions.NotFound()

    # 判断异常是否是没有权限
    elif isinstance(exc, PermissionDenied):
        exc = exceptions.PermissionDenied()

    # 判断异常是否是drf的基类异常,该异常提供了状态码和异常字段detail
    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
        
        # 判断detail是否是list类型或dict类型
        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)

    return None

从上述代码我们可以知道,当response返回为None时,是不会返回异常信息,而是直接抛出异常,所以我们可以自定义异常类
 

自定义异常

在我们的app目录下,创建utils包,并创建exceptions文件,并写入如下源码:

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:
        print(f"{context['view']} - {context['request'].method} - {exc}")
        return Response(status=500, data="服务器错误")
    return response

最后我们将默认异常信息配置改为自己的配置即可,在settings文件中写入如下配置

REST_FRAMEWORK = {
    'EXCEPTION_HANDLER': 'drf_app.utils.exceptions.exception_handler',
}

以后碰到response响应为None的时候,我们就会抛出服务器错误的异常信息
 

总结

为什么要自定义异常模块?

  1. 所有经过drfAPIView视图类产生的异常,都可以提供异常处理方案
  2. drf默认提供了异常处理方案(rest_framework.views.exception_handler),但是处理范围有限
  3. drf提供的处理方案两种,处理了返回异常现象,没处理返回None(后续就是服务器抛异常给前台)
  4. 自定义异常的目的就是解决drf没有处理的异常,让前台得到合理的异常信息返回,后台记录异常具体信息
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/166134.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 女性人物模型_原神人物模型提取

    女性人物模型_原神人物模型提取游戏实战篇|下载原神人物模型并在Unity中给模型添加动画【伯嫖最新原神所有人物模型】拿到模型之后我们就可以自定义在自己的学习项目中使用,非常的Nice!

    2022年10月5日
    2
  • CUMCM→MCM/ICM→NPMCM:关于国赛(全国大学生、研究生、博士研究生数学建模竞赛)和美赛中的数学的专业词汇详细攻略—美国数学建模竞赛

    CUMCM→MCM/ICM→NPMCM:关于国赛(全国大学生、研究生、博士研究生数学建模竞赛)和美赛中的数学的专业词汇详细攻略—美国数学建模竞赛 国赛、美赛各种整理后的资料(有偿提供,替朋友转载,扫描下方二维码提问,或者向博主扫描提问即可获得,2元/份) 数学专业词汇Aabsolutevalue绝对值 accept接受  acceptableregion接受域additivity可加性    adjusted调整的 alternativehypothesis对立假设analysis分析  ana…

    2022年5月8日
    74
  • request对象的作用

    request对象的作用HttpServletRequset:请求报文     代表:浏览器请求时的请求报文,请求到达服务器服务器将报文解析封装为这个对象     获取:请求到服务器是,服务器直接创建然后传入到servlet方法中,最终传入到doget中     作用:获取请求报文中的所有数据              1、获取请求参数【input表…

    2022年5月29日
    43
  • css3动画特效_css3动画效果大全

    css3动画特效_css3动画效果大全CSS3为我们带来了令人惊叹的新特性,而最有趣的就是CSS动画。今天彬Go向大家推荐这50个CSS动画集合可以让你通过使用JavaScript函数来让动画更生动。为了能够预览到这些惊人的CSS3技术带

    2022年8月2日
    7
  • mongodb数据库去重命名_数据库数据去重语句

    mongodb数据库去重命名_数据库数据去重语句  最近写爬虫的时候遇到了一个问题,爬一个专利网站,主要工作流是先把列表页下所有的专利包括专利号、专利名称、URL放到数据库的一个文档info中,再抽取info中的URL进行爬取详情页,爬取列表页的信息做了一个去重,爬一个就在数据库里查一个。。效率就不提了(另一种我能想到的方法是先用线程池爬取一遍,把单个字典放入一个列表中,再采用set去重,但是线程池似乎没法返回子线程的值?),之后在详情页爬取工…

    2022年9月30日
    3
  • 图片下划线 html,HTML <U>下划线标签元素 HTML下划线标签「建议收藏」

    图片下划线 html,HTML <U>下划线标签元素 HTML下划线标签「建议收藏」为html字体下划线样式标签,即对文字实现下划线效果。一、认识html下划线标签U1、htmlU下划线标签语法:以开始,以结束。u标签不是单独一个标签,而是有开始有闭合的一对标签,使用时候切记勿忘记结束,完成一组u下划线标签使用。内容HTML结构语法分析图2、下划线u用法被加下划线HTML下划线U使用效果截图二、htmlU下划线标签使用小实例接下来CSS5对html下划线标签进行小小实…

    2022年6月4日
    36

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号