✨✨ 欢迎大家来到景天科技苑✨✨
🎈🎈 养成好习惯,先赞后看哦~🎈🎈
🏆 作者简介:景天科技苑
🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN新星创作者,掘金优秀博主,51CTO博客专家等。
🏆《博客》:Python全栈,前后端开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,linux,shell脚本等实操经验,网站搭建,面试宝典等分享。
所属的专栏:flask框架零基础,进阶应用实战教学
景天的主页:景天科技苑
此处的全局钩子,其实就是类似django里面的中间件。 也就是只要调用或者注册了,在http请求响应中是必然执行的。
在客户端和服务器交互的过程中,有些准备工作或扫尾工作需要处理,比如:
为了让每个视图函数避免编写重复功能的代码,Flask提供了通用设置的功能,即请求钩子。
请求钩子是通过装饰器的形式实现,Flask支持如下四种请求钩子(注意:钩子的装饰器名字是固定):
before_first_request:
before_request:
after_request
teardown_request:
代码:
from flask import Flask, session # 应用实例对象 app = Flask(__name__) """给app单独设置配置项""" # 设置秘钥 app.config["SECRET_KEY"] = "my SECRET KEY" # @app.before_first_request # def before_first_request(): # """ # 这个钩子会在项目启动后第一次被用户访问时执行 # 可以编写一些初始化项目的代码,例如,数据库初始化,加载一些可以延后引入的全局配置 # """ # print("----before_first_request----") # print("系统初始化的时候,执行这个钩子方法") # print("会在接收到第一个客户端请求时,执行这里的代码") @app.before_request def before_request(): """ 这个钩子会在每次客户端访问视图的时候执行 # 可以在请求之前进行用户的身份识别,以及对于本次访问的用户权限等进行判断。.. """ print("----before_request----") print("每一次接收到客户端请求时,执行这个钩子方法") print("一般可以用来判断权限,或者转换路由参数或者预处理客户端请求的数据") @app.after_request def after_request(response): #注意,这个需要有个参数,用来接收响应 print("----after_request----") print("在处理请求以后,执行这个钩子方法") print("一般可以用于记录会员/管理员的操作历史,浏览历史,清理收尾的工作") response.headers["Content-Type"] = "application/json" response.headers["Company"] = "python.Edu..." # 必须返回response参数 return response @app.teardown_request def teardown_request(exc): print("----teardown_request----") print("在每一次请求以后,执行这个钩子方法") print("如果有异常错误,则会传递错误异常对象到当前方法的参数中") # 在项目关闭了DEBUG模式以后,则异常信息就会被传递到exc中,我们可以记录异常信息到日志文件中 print(f"错误提示:{exc}") # 异常提示 @app.route("/") def index(): print("-----------视图函数执行了---------------") return "ok" if __name__ == '__main__': # 启动项目的web应用程序 app.run(host="0.0.0.0", port=5000, debug=True)
浏览器访问,看到响应头被修改
看下终端打印
先执行before_request,再执行after_request,最后执行teardown_request
我们人为设置个错误,然后让teardown_request接收
当debug=True时,能接收到错误信息
但是页面会报错
当debug=False时,也能接收到错误信息
页面显示500
使用案例:
from flask import Flask,abort,request app = Flask(import_name=__name__) # 配置类 class Config(object): DEBUG = True # 开启调试模式 # 加载配置 app.config.from_object(Config) @app.route("/") def index(): # try: # 1/0 # except: # abort(500) #当请求查询参数中不包含username时,就报错 username = request.args.get("username") if username is None: abort(400) return "ok" if __name__ == '__main__': app.run()
我们先不带查询参数username访问,直接报400错误代码
但是:
abort,只能抛出 HTTP 协议的错误状态码,一般用于权限等页面上错误的展示提示.
abort 在有些前后端分离的项目里面不会被使用,往往在业务错误的时候使用raise进行抛出错误类型,而不是抛出http异常。
案例:
from flask import Flask, request, abort app = Flask(__name__) #自定义一个异常类 class NetWorkError(Exception): pass @app.route("/") def index(): password = request.args.get("password") if password != "123456": # 主动抛出HTTP异常! # abort的第一个参数:表示本次抛出的HTTP异常状态码,后续其他参数,表示错误相关的提示内容。 # abort(400, "密码错误!") raise NetWorkError("网络请求出错!") # print(hello) return "ok" # @app.errorhandler的参数是异常类型或者HTTP状态码 @app.errorhandler(NameError) def NameErrorFunc(exc): """ 针对变量命名的异常处理 :param exc: :return: """ print(exc.__traceback__) return {"error": f"{exc}"} @app.errorhandler(400) def error_400(exc, *args, **kwargs): print(exc.__traceback__) print(exc.code) # 上面abort传递的错误状态码 print(exc.description) # 上面abort传递的错误描述 return {"error": f"{exc.description}"} @app.errorhandler(404) def error_404(exc): print(exc.code) # 上面abort传递的错误状态码 print(exc.description) # 上面abort传递的错误描述 return {"error": "当前页面不存在!"} @app.errorhandler(NetWorkError) def network_error(exc): return {"error": f"{exc}"} if __name__ == '__main__': app.run(host="0.0.0.0", port=5000, debug=True)
1.当我们请求中查询参数不包含password或者password的值不是123456时,我们abort(400, “密码错误”) 抛出密码错误,和400错误状态码
我们通过errorhandler来捕获这个错误状态码,然后返回我们自定义的页面
exc.description就是abort里面的第二个参数,错误描述
浏览器访问
2.当我们通过raise主动抛出一个我们自定义了错误类
此时,我们根据错误类型来捕获,并返回指定页面
浏览器访问
3.当我们打印一个不存在的变量,报NameError时
通过errorhandler捕获
浏览器访问,可以显示我们返回的页面内容
4.当我们访问一个不存在的url,我们捕获404报错,然后返回指定页面
浏览器访问
总结:
综上就是flask请求钩子的设置方式,以及在什么情况下用什么样的请求钩子,主动抛出异常的方式,对异常的捕获,返回更好看的异常显示页面等等,感兴趣的朋友可以一键三连,flask持续更新中!!!
上一篇:Spring IoC&DI(2)