- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章python中通过Django捕获所有异常的处理由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
在项目中统一异常处理,可以防止代码中有未捕获的异常出现。本文介绍如何在 Django 项目中进行统一异常的处理,再结合状态码枚举类对项目异常信息进行日志记录.
。
在 Django 项目中可以自定义 中间件类 继承 django.middleware.common 下的 MiddlewareMixin 中间件类,重写 process_exception 方法的异常处理逻辑,然后在项目配置下的 中间件中注册 即可进行全局异常处理.
我是在项目自定义的 utils 包下 middlewares.py 模块中下进行中间件的编写.
# middlewares.py#!/usr/bin/python3# -*- coding: utf-8 -*-# @Author: Hui# @Desc: { 项目中间件模块 }# @Date: 2021/09/24 8:18from django.middleware.common import MiddlewareMixinclass ExceptionMiddleware(MiddlewareMixin): """统一异常处理中间件""" def process_exception(self, request, exception): """ 统一异常处理 :param request: 请求对象 :param exception: 异常对象 :return: """ # 异常处理 print(exception) return None
这里暂时先简单进行异常输出,来模拟异常处理。最后不要忘记 在配置文件中注册中间件。django 项目默认的配置文件是 settings.py 我这里只是把配置文件单独放到了 settings 包下然后改了文件名.
process_exception 方法介绍 。
process_exception 方法只有在视图函数中出现异常了才执行。该方法的返回值可以是一个 None 也可以是一个 HttpResponse 对象.
None
,页面会报 500 状态码错误,视图函数不会执行。HttpResponse
对象,则是对应的响应信息,页面不会报错。中间件中的方法 。
。
方法 | 作用 |
---|---|
process_request(self,request) |
在视图函数之前执行 |
process_view(self, request, view_func, view_args, view_kwargs) |
视图函数之前,process_request 方法之后执行 |
process_exception(self, request, exception) |
视图函数中出现异常了才执行 |
process_response(self, request, response) |
视图函数之后执行 |
下面一图就能比较好的呈现 django 整个处理流程逻辑 。
更多的中间件细节可以去 Django 官方文档 进行了解.
。
结合自定义的异常和状态码枚举类,进行异常日志信息和业务逻辑的处理.
# exceptions.py#!/usr/bin/python3# -*- coding: utf-8 -*-# @Author: Hui# @Desc: { 项目异常模块 }# @Date: 2021/09/24 8:14class CommonException(Exception): """公共异常类""" def __init__(self, enum_cls): self.code = enum_cls.code self.errmsg = enum_cls.errmsg self.enum_cls = enum_cls # 状态码枚举类 super().__init__()class BusinessException(CommonException): """业务异常类""" passclass APIException(CommonException): """接口异常类""" pass
# enums.py#!/usr/bin/python3# -*- coding: utf-8 -*-# @Author: Hui# @Desc: { 项目枚举类模块 }# @Date: 2021/09/23 23:37from enum import Enumclass StatusCodeEnum(Enum): """状态码枚举类""" OK = (0, '成功') ERROR = (-1, '错误') SERVER_ERR = (500, '服务器异常') IMAGE_CODE_ERR = (4001, '图形验证码错误') THROTTLING_ERR = (4002, '访问过于频繁') NECESSARY_PARAM_ERR = (4003, '缺少必传参数') USER_ERR = (4004, '用户名错误') PWD_ERR = (4005, '密码错误') CPWD_ERR = (4006, '密码不一致') MOBILE_ERR = (4007, '手机号错误') SMS_CODE_ERR = (4008, '短信验证码有误') ALLOW_ERR = (4009, '未勾选协议') SESSION_ERR = (4010, '用户未登录') REGISTER_FAILED_ERR = (4011, '注册失败') DB_ERR = (5000, '数据库错误') EMAIL_ERR = (5001, '邮箱错误') TEL_ERR = (5002, '固定电话错误') NODATA_ERR = (5003, '无数据') NEW_PWD_ERR = (5004, '新密码错误') OPENID_ERR = (5005, '无效的openid') PARAM_ERR = (5006, '参数错误') STOCK_ERR = (5007, '库存不足') @property def code(self): """获取状态码""" return self.value[0] @property def errmsg(self): """获取状态码信息""" return self.value[1]
状态码枚举类的设计可以查阅 巧用Python 枚举类设计状态码信息 。
统一前后端交互数据和异常信息结果.
# result.py#!/usr/bin/python3# -*- coding: utf-8 -*-# @Author: Hui# @Desc: { 项目信息返回结果模块 }# @Date: 2021/09/23 22:10from .enums import StatusCodeEnumclass R(object): """ 统一项目信息返回结果类 """ def __init__(self): self.code = None self.errmsg = None self._data = dict() @staticmethod def ok(): """ 组织成功响应信息 :return: """ r = R() r.code = StatusCodeEnum.OK.code r.errmsg = StatusCodeEnum.OK.errmsg return r @staticmethod def error(): """ 组织错误响应信息 :return: """ r = R() r.code = StatusCodeEnum.ERROR.code r.errmsg = StatusCodeEnum.ERROR.errmsg return r @staticmethod def server_error(): """ 组织服务器错误信息 :return: """ r = R() r.code = StatusCodeEnum.SERVER_ERR.code r.errmsg = StatusCodeEnum.SERVER_ERR.errmsg return r @staticmethod def set_result(enum): """ 组织对应枚举类的响应信息 :param enum: 状态枚举类 :return: """ r = R() r.code = enum.code r.errmsg = enum.errmsg return r def data(self, key=None, obj=None): """统一后端返回的数据""" if key: self._data[key] = obj context = { 'code': self.code, 'errmsg': self.errmsg, 'data': self._data } return context
# middlewares.py#!/usr/bin/python3# -*- coding: utf-8 -*-# @Author: Hui# @Desc: { 项目中间件模块 }# @Date: 2021/09/24 8:18import loggingfrom django.db import DatabaseErrorfrom django.http.response import JsonResponsefrom django.http import HttpResponseServerErrorfrom django.middleware.common import MiddlewareMixinfrom meiduo_mall.utils.result import Rfrom meiduo_mall.utils.enums import StatusCodeEnumfrom meiduo_mall.utils.exceptions import BusinessExceptionlogger = logging.getLogger('django')class ExceptionMiddleware(MiddlewareMixin): """统一异常处理中间件""" def process_exception(self, request, exception): """ 统一异常处理 :param request: 请求对象 :param exception: 异常对象 :return: """ if isinstance(exception, BusinessException): # 业务异常处理 data = R.set_result(exception.enum_cls).data() return JsonResponse(data) elif isinstance(exception, DatabaseError): # 数据库异常 r = R.set_result(StatusCodeEnum.DB_ERR) logger.error(r.data(), exc_info=True) return HttpResponseServerError(StatusCodeEnum.SERVER_ERR.errmsg) elif isinstance(exception, Exception): # 服务器异常处理 r = R.server_error() logger.error(r.data(), exc_info=True) return HttpResponseServerError(r.errmsg) return None
。
让我们来看一段注册校验功能业务逻辑 。
def verify_params(self, request): """ 校验注册信息 :param request: 注册请求对象 :return: response_ret """ # 接受参数 self.username = request.POST.get('username') self.password = request.POST.get('password') self.confirm_pwd = request.POST.get('confirm_pwd') self.mobile = request.POST.get('mobile') self.allow = request.POST.get('allow') if not all(all_args): # raise BusinessException(StatusCodeEnum.PARAM_ERR) response_ret = http.HttpResponseForbidden('参数错误') return response_ret # 用户名 5-20个字符 if not re.match(r'^[a-zA-Z0-9_]{5,20}', self.username): response_ret = http.HttpResponseForbidden('用户名不规范') return response_ret # 密码 8-20个字符 if not re.match(r'^[a-zA-Z0-9]{8,20}', self.password): response_ret = http.HttpResponseForbidden('密码不规范') return response_ret # 两次密码一致性 if self.password != self.confirm_pwd: response_ret = http.HttpResponseForbidden('两次密码不一致') return response_ret # 手机号合法性 if not re.match(r'^1[3-9]\d{9}$', self.mobile): response_ret = http.HttpResponseForbidden('手机号码不合法') return response_ret # 是否勾选用户协议 if self.allow != 'on': response_ret = http.HttpResponseForbidden('请勾选用户协议') return response_ret return response_ret
通过抛异常和设置状态码枚举来处理 。
def verify_params(self, request): """ 校验注册信息 :param request: 注册请求对象 :return: response_ret """ # 接受参数 self.username = request.POST.get('username') self.password = request.POST.get('password') self.confirm_pwd = request.POST.get('confirm_pwd') self.mobile = request.POST.get('mobile') self.allow = request.POST.get('allow') # 校验参数 all_args = [self.username, self.password, self.confirm_pwd, self.mobile, self.allow] if not all(all_args): raise BusinessException(StatusCodeEnum.PARAM_ERR) # 用户名 5-20个字符 if not re.match(r'^[a-zA-Z0-9_]{5,20}', self.username): raise BusinessException(StatusCodeEnum.USER_ERR) # 密码 8-20个字符 if not re.match(r'^[a-zA-Z0-9]{8,20}', self.password): raise BusinessException(StatusCodeEnum.PWD_ERR) # 两次密码一致性 if self.password != self.confirm_pwd: raise BusinessException(StatusCodeEnum.CPWD_ERR) # 手机号合法性 if not re.match(r'^1[3-9]\d{9}$', self.mobile): raise BusinessException(StatusCodeEnum.MOBILE_ERR) # 是否勾选用户协议 if self.allow != 'on': raise BusinessException(StatusCodeEnum.ALLOW_ERR)
减少 try ... except ... 代码块 。
例如在对数据库进行操作时,为了防止数据库发生了意外的异常导致系统崩溃,通常加上 try ... except ...来记录异常信息。然而配置了全局异常处理,则可以不用管理.
# 创建用户try: user = User.objects.create_user( username=self.username, password=self.password, mobile=self.mobile, )except DatabaseError as e: logger.error(e) # 有了全局的异常处理user = User.objects.create_user( username=self.username, password=self.password, mobile=self.mobile, )
注意:如果需要通过异常捕获来处理一些业务信息,则不可避免,如事务回滚等 。
。
可能通过文章方式不好理解其思想,大家可以通过项目源代码的方式来参考.
美多商城 https://gitee.com/huiDBK/meiduo_project/tree/master 。
。
用 Code 谱写世界,让生活更有趣.
万水千山总是情,点赞再走行不行.
码字不易,还望各位大侠多多支持.
到此这篇关于python中通过Django捕获所有异常的处理的文章就介绍到这了,更多相关python Django捕获异常内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。
原文链接:https://blog.csdn.net/qq_43629857/article/details/120480250 。
最后此篇关于python中通过Django捕获所有异常的处理的文章就讲到这里了,如果你想了解更多关于python中通过Django捕获所有异常的处理的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
多个 ChildException catch block 和一个 Exception catch block 之间哪个更好? 更好,我的意思是以良好的实践方式。 举例说明: public stati
我正在尝试将脱机计算机记录在文本文件中,以便以后可以再次运行它们。似乎没有被记录或捕获。 function Get-ComputerNameChange { [CmdletBinding()]
我正在将 Scala 'try/catch' 测试代码转换为使用 'intercept' 有没有我不应该使用“拦截”的场景?使用 'intercept' 而不是 'try/catch' 的唯一好处是简
我对erlang很陌生,我正在尝试使用基本的try/catch语句来工作。我正在使用Webmachine处理一些请求,我真正想做的就是解析一些JSON数据并将其返回。如果JSON数据无效,我只想返回一
我不知道如何捕获删除按键。我发现在 ASCII 代码表中,它位于 127 位,但是 if (Key = #127) then 却无济于事。 然后我检查了 VK_DELETE 的值,它是 47。尝试使用
我很少在失败时对数据库查询使用唯一的错误消息 我经常使用简短的标准消息,例如“数据库错误/失败。请与网站管理员联系”或类似的消息。或自动发送给我 我正在寻找一种在PDO中全局设置一次try {}和ca
我有一个变量CompletableFuture completableFuture 。我希望能够使用任何类型的对象来完成它。例如:completableFuture.complete(new Stri
我认为这是基本的东西,但我不知道该怎么做。为什么我得到 IOException never throw in body of相应的 try 语句 public static void main(Str
我在此代码中遇到 JSON 异常: JSONObject jObject = new JSONObject(JSONString); pontosUsuario.setIdUsuari
我正在尝试打印出用单引号括起来的文本。 /bin/bash -lc '/home/CASPER_REPORTS/scripts/CASPER_gen_report.sh CASPER_1' /bin/
我这里遇到了一点问题。我想弄清楚如何捕获 IllegalArgumentException。对于我的程序,如果用户输入负整数,程序应该捕获 IllegalArgumentException 并询问用户
我无法理解 EJBTransactionRolledbackException。 我有实体: @Entity public class MyEntity { @Id @Generate
对于我给自己提出的以下挑战,如果社区的经验给我任何建议,我将不胜感激 - 即,这里有任何关于最佳方法/方向的指示吗? 要求 允许收集/实时监控从用户 Windows PC 到一组特定 IP 地址(或
我想在我的 ABAP 代码中捕获并处理 SAPSQL_DATA_LOSS。 我试过这个: try. SELECT * FROM (rtab_name) AS rtab
我知道捕获错误不是一个好的做法,但在这种情况下,这样做很重要。我正在尝试运行一个包含游戏一部分的 jar,但它给了我一个 unsatisfiedlink 错误,但这是有趣的部分:我正在使用这段代码:
我有一个表单页面,当我保存它时,它会覆盖数据库。表单页面中有一个文本框,允许用户输入 4000 个字符,但如果用户输入的字符超过此值,则会出现以下错误: ERROR 15:54:05 Abstrac
我想知道在python中绑定(bind)键的最简单方法 例如,默认的 python 控制台窗口出现并等待,然后在 psuedo -> if key "Y" is pressed: print (
下面是别人写的类。 我面临的问题是,当它进入parse method时与 null as the rawString ,它正在扔NumberFormatException 。 所以我想做的是,我应该捕
我有一个简单的脚本,可以捕获所有鼠标单击,除非您单击实际有效的内容。链接、Flash 视频等。我如何调整它,以便无论用户点击什么,在视频加载、新页面加载等之前,它都会发送我构建的简单 GET 请求?
我有一个带有一些选择列表的表单,当选择某些值时,这些列表将显示/隐藏更多输入字段。 问题是大多数用户都是数据输入人员,因此他们在输入数据时大量使用键盘,并且选择列表的 change 事件仅在焦点离开输
我是一名优秀的程序员,十分优秀!