DRF渲染之异常处理

异常处理

【1 】引言

Django REST Framework 这个就是我们常常说的DRF

  1. APIView的dispatch方法
    • 当请求到达视图时,DRF 的 APIView 类会调用 dispatch 方法来处理请求。
    • dispatch 方法中,有一个关键的步骤是处理异常。如果在视图类的方法执行过程中出现了异常,DRF 会捕获这个异常,并调用 self.handle_exception(exc) 方法来处理它。
  2. handle_exception 方法
    • handle_exception 方法用于处理异常,它首先获取异常处理函数的引用,这个函数的地址存储在配置中,通常是 settings.EXCEPTION_HANDLER
    • 然后,handle_exception 调用这个异常处理函数,并传入两个参数:异常对象 exc 和上下文 context
    • 异常处理函数执行后会返回一个响应对象,这个响应对象会在异常发生时返回给客户端。
  3. rest_framework.views.exception_handler 函数
    • 这个函数是 DRF 提供的默认异常处理函数。它会检查传入的异常是否是 DRF 内置的 exceptions.APIException 类型的异常。
    • 如果是 APIException 类型的异常,这个函数会根据异常类型组装一个响应对象,并返回。
    • 如果异常不是 APIException 类型的,则返回 None,意味着这个异常不是 DRF 能处理的,需要由其他方式处理(比如由 Django 的默认异常处理机制处理)。

​ 总的来说,DRF 的异常处理机制允许你在视图类中捕获并处理异常,并提供了一个灵活的机制来定义和定制异常处理方式。

读APIView源码时,即是三大认证和视图类的方法中出现了异常,都会被try捕获,做全局异常处理:response = self.handle_exception(exc)-只要出了异常,都会执行response = self.handle_exception(exc)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

     def handle_exception(self, exc):# 拿到一个函数内存地址--》配置文件中配置了# self.settings.EXCEPTION_HANDLER# 拿到这个函数:rest_framework.views.exception_handlerexception_handler = self.get_exception_handler()# 执行这个函数,传入俩参数response = exception_handler(exc, context)# drf的 Response的对象return response-rest_framework.views.exception_handler 逻辑分析-判断异常是不是 drf内 exceptions.APIException的异常-如果是--》组装了Response返回了-如果不是--》返回了None-总结:默认drf只处理了自己的异常,django的异常,它没处理,直接前端能看到
  • 而-handle_exception 源码分析里面的重点则是

  1. 异常类型检查:
    • if isinstance(exc, (exceptions.NotAuthenticated, exceptions.AuthenticationFailed)): 这里检查异常是否是用户未认证或认证失败引起的。
  2. 认证头部信息获取:
    • auth_header = self.get_authenticate_header(self.request): 尝试获取适当的认证头部信息,用于构建响应。
    • if auth_header:: 如果成功获取了认证头部信息,则将其添加到异常对象中,否则将响应状态码设置为 403 Forbidden。
  3. 异常处理程序调用:
    • exception_handler = self.get_exception_handler(): 获取异常处理程序。
    • context = self.get_exception_handler_context(): 获取异常处理上下文。
    • response = exception_handler(exc, context): 将异常对象和上下文传递给异常处理程序,获取处理后的响应。
  4. 响应处理:
    • if response is None:: 如果异常处理程序返回了 None,表示没有提供一个适当的响应,这时会重新引发异常。
    • response.exception = True: 将响应对象的 exception 属性设置为 True,表示这个响应是由异常引起的。
    • return response: 返回处理后的响应。

​ 这些部分共同构成了异常处理器的核心功能,负责捕获、处理异常,并生成适当的响应。

总结:默认drf只处理了自己的异常,django的异常,它没处理,直接前端能看到

【 2 】简单示例

  • urls.py

from three.views import  TeyView
# 自动生成路由
from rest_framework.routers import SimpleRouter, DefaultRouter
from django.urls import path, include# 2 实例化得到对象
# router = SimpleRouter()
router = DefaultRouter()
# 3 执行对象的方法
router.register('User', UserTokenView, 'User')
urlpatterns = [path('try/', TeyView.as_view()),]
# 5 把自动生成的路由,放到 urlpatterns中
urlpatterns += router.urls
from rest_framework.views import APIView
from rest_framework.exceptions import ValidationError,AuthenticationFailedclass TeyView(APIView):def get(self,request):# drf的异常# 主动抛出异常!!!raise ValidationError('校验失败')# raise AuthenticationFailed('失败了这么棒!!')# # diango的异常# res = 9/0# return Response('zheng1casd')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

【 2 】使用步骤

全局处理,如何使用

  • 写个函数
  • 在函数中处理异常,统一返回格式
  • 在配置文件中配置:只要出了异常,执行我们自己的
  • 写完配置文件
    REST_FRAMEWORK = {'EXCEPTION_HANDLER': 'three.exceptions.common_exception_handler',}

异常处理函数

​ 创建exceptions.py文件

from rest_framework.views import exception_handler
from rest_framework.response import Responsedef common_exception_handler(exc, context):# 【1】 返回 Response: 说明是drf的一次# 【2】 返回None: 就不是drf的异常# response.datak可以拿到主体的数据response = exception_handler(exc, context)if response:if isinstance(response.data, dict):errors = response.data.get('detail', '系统正在维修,请联系站长')elif isinstance(response.data, list):errors = response.data[0]else:errors = r'请重新启动或者打自己一巴掌!!!'response = Response({r'code': 444, "msg": f"【drf】:{errors}"})else:# 获取报错异常的类型print(type(exc))# <class 'IndexError'>if response is not None:response.data['0'] = '你是'elif isinstance(exc,IndexError):response = Response({r'code': 499, "msg": f"IndexError数据不对"})else:errors = str(exc)response = Response({r'code': 404, "msg": f"【django】:{errors}"})return response

注意使用这个的前提就是有异常我们可以定义

from rest_framework.views import APIView
from rest_framework.exceptions import ValidationError,AuthenticationFailed,APIExceptionclass TeyView(APIView):def get(self,request):# drf的异常# 主动抛出异常!!!# raise APIException('校验失败')# raise AuthenticationFailed('失败了这么棒!!')# # diango的异常# res = 9/0a = [1,2,3,4,5,6]print(a[9])return Response('zheng1casd')---------------------------------------
# urls.py
from three.views import  TeyView
# 自动生成路由
from rest_framework.routers import SimpleRouter, DefaultRouter
from django.urls import path, include# 2 实例化得到对象
# router = SimpleRouter()
router = DefaultRouter()
# 3 执行对象的方法
router.register('User', UserTokenView, 'User')
urlpatterns = [path('try/', TeyView.as_view()),]
# 5 把自动生成的路由,放到 urlpatterns中
urlpatterns += router.urls

【3】自定义异常捕获

class PassException(Exception):def __init__(self,msg):self.msg=msg

因为这里并不是一个合格的PassException异常但这个是一个ZeroDivisionError所以有了点手段

from .exceptions import PassException
class TeyView(APIView):def get(self,request):# drf的异常# 主动抛出异常!!!# raise APIException('校验失败')# raise AuthenticationFailed('失败了这么棒!!')try:# 这里是你可能会出现除零错误的代码res = 1 / 0except ZeroDivisionError:# 捕获除零错误,并抛出 PassException 异常raise PassException('4564')
def common_exception_handler(exc, context):...else:...else:if isinstance(exc, PassException):  # 检查是否是 PassExceptionresponse = Response({'code': 499, "msg": f"PassException: {exc.msg}"})...return response

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

【 4 】加强

 # 日志记录放这里即可:请求方式,请求的地址,客户端ip,用户id,时间
from rest_framework.views import exception_handler
from rest_framework.response import Responseclass PassException(Exception):def __init__(self,msg):self.msg=msgdef common_exception_handler(exc, context):# 【1】 返回 Response: 说明是drf的一次# 【2】 返回None: 就不是drf的异常# response.datak可以拿到主体的数据request = context.get('request')view = context.get('view')  # 哪个视图类出的错user_id = request.user.pk or '匿名用户'print(f'请求方式是:{request.method},请求地址是:{request.get_full_path()},客户端ip:{request.META.get("REMOTE_ADDR")},用户id:{user_id}')print(type(exc))response = exception_handler(exc, context)if response:if isinstance(response.data, dict):errors = response.data.get('detail', '系统正在维修,请联系站长')elif isinstance(response.data, list):errors = response.data[0]else:errors = r'请重新启动或者打自己一巴掌!!!'response = Response({r'code': 444, "msg": f"【drf】:{errors}"})else:# 获取报错异常的类型print(type(exc))# <class 'IndexError'>if response is not None:response.data['0'] = '你是'elif isinstance(exc,IndexError):response = Response({r'code': 499, "msg": f"IndexError数据不对"})elif isinstance(exc,PassException):response = Response({r'code': 999, "msg": f"这个是PassException报错"})else:errors = str(exc)response = Response({r'code': 404, "msg": f"【django】:{errors}"})return response
  • 最终版本
from rest_framework.views import exception_handler
from rest_framework.response import Response
import loggingclass PassException(Exception):def __init__(self,msg):self.msg=msg# 创建日志记录器
logger = logging.getLogger(__name__)def common_exception_handler(exc, context):# 【1】 返回 Response: 说明是drf的一次# 【2】 返回None: 就不是drf的异常# response.data可以拿到主体的数据request = context.get('request')view = context.get('view')  # 哪个视图类出的错user_id = request.user.pk or '匿名用户'# 记录请求信息到日志# logger.info(#     f'请求方式是:{request.method}, 请求地址是:{request.get_full_path()}, 客户端IP:{request.META.get("REMOTE_ADDR")}, 用户ID:{user_id}')print(f'请求方式是:{request.method},请求地址是:{request.get_full_path()},客户端ip:{request.META.get("REMOTE_ADDR")},用户id:{user_id},视图类:{view.__class__.__name__}')print(type(exc))response = exception_handler(exc, context)if response:if isinstance(response.data, dict):errors = response.data.get('detail', '系统正在维修,请联系站长')elif isinstance(response.data, list):errors = response.data[0]else:errors = r'请重新启动或者打自己一巴掌!!!'response = Response({r'code': 444, "msg": f"【drf】:{errors}"})else:# 获取报错异常的类型print(type(exc))# <class 'IndexError'>if response is not None:response.data['0'] = '你是'elif isinstance(exc,IndexError):response = Response({r'code': 499, "msg": f"IndexError数据不对"})elif isinstance(exc,PassException):response = Response({r'code': 999, "msg": f"这个是PassException报错"})else:errors = str(exc)response = Response({r'code': 404, "msg": f"【django】:{errors}"})return response

【 5 】模板

  • 简易版本

# 后期视图的方法,可以写成这种模板
try:# 核心逻辑if 某个条件不符合:  # 或断言raise NoPermissionExceptionexcept NoPermissionException as e:# return Response({'code':888,'msg':'错误'})raise NoPermissionException('没有权限')except AAException as e:raise NoPermissionException('没有权限')return Response('ok')
  • 加强版本

from rest_framework.response import Response  
from rest_framework.exceptions import PermissionDenied  # 或者您自定义的 NoPermissionException  
from .exceptions import AAException  # 假设 AAException 是您自定义的异常  def my_view(request):  try:  # 核心逻辑  if 某个条件不符合:  # 或断言  raise PermissionDenied('没有权限')  # 使用DRF的PermissionDenied异常  # 其他逻辑...  except PermissionDenied as e:  return Response({'code': 888, 'msg': str(e)}, status=403)  # 403 Forbidden  except AAException as e:  return Response({'code': 999, 'msg': 'AAException 触发的错误'}, status=400)  # 400 Bad Request 或者其他合适的状态码  # 其他异常处理...  # 视图正常执行完毕后的返回  return Response('ok')

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/9976.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

加速vivado编译工程

系统环境&#xff1a;windows11IDE环境&#xff1a;vivado2023.2工程&#xff1a;vivado自带的example project&#xff08;wave_gen&#xff09; Vivado支持多线程&#xff0c;可进一步缩短编译时间&#xff0c;这需要通过如下的Tcl脚本进行设置。综合阶段&#xff0c;Vivado可…

东软集团:用软件、大模型、生态领航智能汽车软件新纪元

“ 这是一次里程碑式的重大升级。 ” 整理 | 云舒 编辑 | 小白 出品&#xff5c;极新 在“新时代 新汽车”2024北京车展上&#xff0c;法拉利、保时捷、宾利、奔驰、宝马、奥迪、路虎、本田、尼桑、铃木以及极氪、零跑、赛力斯、AION埃安等都是东软的伙伴&#xff0c;当然还…

读天才与算法:人脑与AI的数学思维笔记24_预测性文本生成器

1. 起源 1.1. 人类讲故事可能起源于“假如……”这种问答结构 1.2. 讲故事是人类做安全试验的一种方式 1.2.1. 如果你问一个人“假如……”&#xff0c;其实是在探索你的行为对他可能带来的影响 1.3. 最早出现的故事极有可能就源自我们对在周遭混乱的环境中寻找某种秩序的渴…

书生作业:XTuner

作业链接&#xff1a; https://github.com/InternLM/Tutorial/blob/camp2/xtuner/homework.md xtuner: https://github.com/InternLM/xtuner 环境配置 首先&#xff0c;按照xtuner的指令依次完成conda环境安装&#xff0c;以及xtuner库的安装。 然后&#xff0c;我们开始尝试…

activiti 工作流基本使用

Activiti 介绍 Activiti 是一个开源架构的工作流引擎&#xff0c;基于bpmn2.0 标准进行流程定义。其前身是JBPM&#xff0c;Activiti 通过嵌入到业务系统开发中进行使用。 官方是这样介绍 activiti的&#xff1a; Activiti 是领先的轻量级、以 Java 为中心的开源 BPMN 引擎&…

java发送请求-二次开发-get请求json

这里有2个判断 如果param为空则对url发送请求 再继续判断有值时&#xff0c;接口参数时json还是namevalue格式 因为json是带{,所以可以先写为param包含{}, 反之就是请求格式是url&#xff1f;param 请求json要带参数&#xff0c;所以需要使用setEntity方法&#xff0c; 最…

泰迪智能科技携手新乡学院开展“泰迪智能双创工作室”共建交流会

为深化校企合作&#xff0c;实现应用型人才培养目标。5月8日&#xff0c;广东泰迪智能科技股份有限公司河南分公司市场总监张京瑞到访新乡学院数学与统计学院参观交流&#xff0c;数学与统计学院院长赵国喜、副院长皮磊、张秦&#xff0c;教研室主任许寿方、姚广出席本次交流会…

arp icmp 等报文格式

ARP报文格式 ARP是一个独立的三层协议&#xff0c;所以ARP报文在向数据链路层传输时不需要经过IP协议的封装&#xff0c;而是直接生成自己的报文&#xff0c;其中包括ARP报头&#xff0c;到数据链路层后再由对应的数据链路层协议&#xff08;如以太网协议&#xff09;进行封装…

【Qt 学习笔记】Qt常用控件 | 多元素控件 | Table Widget的说明及介绍

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ Qt常用控件 | 多元素控件 | Table Widget的说明及介绍 文章编号&#…

美港通正规炒股市场美股证券市场地产股的春天 来了吗?

查查配地产股的春天 来了吗? 美港通证券以其专业的服务和较低的管理费用在市场中受到不少关注。该平台提供了实盘交易、止盈止损、仓位控制等功能,旨在为投资者提供更为全面的投资体验。 昨天房地产行业的大事可真不少!早间,杭州宣布全面取消住房限购,不再审核购房资格。杭州…

Git详解之五:分布式Git

为了便于项目中的所有开发者分享代码&#xff0c;我们准备好了一台服务器存放远程 Git 仓库。经过前面几章的学习&#xff0c;我们已经学会了一些基本的本地工作流程中所需用到的命令。接下来&#xff0c;我们要学习下如何利用 Git 来组织和完成分布式工作流程。 特别是&#…

OpenCV使用 Kinect 和其他兼容 OpenNI 的深度传感器(75)

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇:使用 OpenCV 创建视频(74) 下一篇 :OpenCV使用 Orbbec Astra 3D 相机(76) 目的&#xff1a;​ 通过 VideoCapture 类支持与 OpenNI 兼容的深度传感器&#xff08;Kinect、XtionPRO 等&#xff09;。…

【影片欣赏】【指环王】【魔戒:国王归来 The Lord of the Rings: The Return of the King】

往期魔戒博客见&#xff1a; 【影片欣赏】【指环王】【魔戒&#xff1a;护戒使者 The Lord of the Rings: The Fellowship of the Ring】 【影片欣赏】【指环王】【魔戒&#xff1a;双塔奇谋 The Lord of the Rings: The Two Towers】 2004年发行&#xff0c;Special Extend…

K8s源码分析(二)-K8s调度队列介绍

本文首发在个人博客上&#xff0c;欢迎来踩&#xff01; 本次分析参考的K8s版本是 文章目录 调度队列简介调度队列源代码分析队列初始化QueuedPodInfo元素介绍ActiveQ源代码介绍UnschedulableQ源代码介绍**BackoffQ**源代码介绍队列弹出待调度的Pod队列增加新的待调度的Podpod调…

IP定位技术在打击网络犯罪中的作用

随着互联网的普及和信息技术的发展&#xff0c;网络犯罪日益猖獗&#xff0c;给社会治安和个人财产安全带来了严重威胁。而IP定位技术的应用为打击网络犯罪提供了一种有效手段。IP数据云将探讨IP定位技术在打击网络犯罪中的作用及其意义。 1. IP定位技术的原理 IP&#xff08…

国产操作系统上使用HHDESK桌面运维工具 _ 统信UOS _ 麒麟

原文链接&#xff1a;国产操作系统上使用HHDESK桌面运维工具 | 统信UOS | 麒麟 Hello&#xff0c;大家好啊&#xff01;在多功能软件的帮助下&#xff0c;日常的计算机操作可以变得更加高效便捷。今天&#xff0c;我要向大家介绍的是HHDESK&#xff0c;这是一款功能丰富的工具&…

点云工具 CloudCompare 查看三维模型

CloudCompare 是一款三维点云&#xff08;Point Cloud&#xff09;处理软件&#xff0c;可以方便地使用计算法向量、优化法向量、泊松构网、滤波等功能。 工具下载地址&#xff1a;nullCloudCompare website entry pagehttps://cloudcompare.org/ github地址&#xff1a; GitH…

【JavaEE网络】用Form与Ajax构建HTTP请求

目录 通过 form 表单构造 HTTP 请求form 发送 GET 请求form 发送 POST 请求 通过 ajax 构造 HTTP 请求发送 GET 请求发送 POST 请求发送 application/json 数据封装 ajax 方法 通过 form 表单构造 HTTP 请求 form (表单) 是 HTML 中的一个常用标签. 可以用于给服务器发送 GET …

权限束缚术--权限提升你需要知道这些

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文主要对渗透测试中权限提升的一些基础知识进行整理 并不包含权限提升的具体操作 适合要入门权限提升的朋友 提权的重要性 我们在渗透网站时&#xff0c;我们往往会拿到一些权限&#xff0c;但是我们的权限有…

Mybatis之ResultMap

前言 select语句查询得到的结果集是一张二维表&#xff0c;水平方向上看是一个个字段&#xff0c;垂直方向上看是一条条记录。而Java是面向对象的程序设计语言&#xff0c;对象是根据类定义创建的&#xff0c;类之间的引用关系可以认为是嵌套的结构。在JDBC编程中&#xff0c;…