Flask笔记六之中间件操作

本文首发于公众号:Hunter后端

原文链接:Flask笔记六之中间件操作

与 Django 一样,Flask 也提供了中间件的使用,用于在处理请求之前和之后执行一些公共逻辑

本篇笔记的代码都已经提交到 github 上,可使用下面的操作获取代码:

git clone https://github.com/x1204604036/flask_backend.git

1、Django 中间件使用示例

在 Django 中,我们可以先定义一个中间件,然后在 settings.py 中注册,中间件的内容大致如下:

# huter/middleware.pyclass SimpleMiddleware:def __init__(self, get_response):self.get_response = get_responsedef __call__(self, request):# 在请求进入视图函数前的可以执行一些操作,针对 requestprint(request.path)response = self.get_response(request)# 在处理完请求后,可以执行一些操作,针对 response# log_response_info()return response

在 Django 中,请求处理前的 request 参数和处理后返回的 response 都可以在一个中间件里操作完成

2、Flask 的中间件介绍

Flask 中,中间件通过装饰器来使用,被分为两部分,一个是请求前,用 @app.before_request 来操作,一个是请求后,用 @app.after_request 来操作。

接下来介绍一下中间件从注册到使用的操作。

1. 中间件定义

这里我们定义两个测试用的中间件,我们在 app/utils/ 文件夹下创建一个 middlewares 的文件夹,其下再创建一个文件 middlewares.py

# app/utils/middlewares/middlewares.pydef register_middleware(app):@app.before_requestdef before_request_test():print("before request")@app.after_requestdef after_request_test(response):print("after request")return response

@app.before_request 修饰的函数表示在请求处理前进行的操作,这里是简单的打印一条消息,除此之外,我们还可以在这里对登录进行验证。

这样的话,在前面的笔记里我们对接口进行的 @login_required 的装饰器就不需要了,就不要在每个接口前都进行这种装饰,可以使代码变得简洁,同样实现我们想要的功能

除此之外,还可以对请求的信息进行日志记录,比如请求的接口名称啊,请求的参数啊等等

@app.after_request 修饰的函数表示在请求处理完成后进行的操作,我们可以对返回的 response 的数据增加一些参数等,其中,一个 response 的内容我们打印出它的 response.__dict__ 可以看到它的数据结构如下所示:

# response.__dict__{'_charset': 'utf-8', 'headers': Headers([('Content-Type', 'application/json'), ('Content-Length', '75')]), '_status': '200 OK', '_status_code': 200, 'direct_passthrough': False, '_on_close': [], 'response': [b'{\n  "code": 0,\n  "msg": "success",\n  "user_info": {\n    "user_id": 1\n  }\n}\n']}

当然,上面的操作还需要在 app 中注册之后才可以使用。

2. 中间件引入注册

要使用中间件,则需要进行引入注册操作,在这里,即为调用上面的 register_middleware() 函数,我们在 app/__init__.py 中操作如下:

# app/__init__.pyfrom app.utils.middlewares.middlewares import register_middlewaredef create_app():app = Flask(__name__)register_middleware(app)return app

引入后重启服务,然后调用一个接口,就可以看到日志里会输出前面测试的两个中间件打印出的信息

接下来我们创建两个中间件,用于实现登录的校验和接口请求的日志记录,在此之前,先介绍一下 Flask 里的 g 对象

3、g 对象

Flask 里有一个 g 对象的概念,它可以用于在一个请求周期内存储共享的临时数据,但是仅限于一个请求周期。

比如客户端发起了两次请求,我们在第一个请求里保存到 g 对象里的数据就随着第一个请求的 response 的返回就销毁了,第二次请求是一个全新的 g 对象。

这个其实和 session 对象有相似之处,但是 session 是跨请求周期的,比如第一个接口登录,保存了 user_id 登录信息,第二个接口再次请求还可以读取到这个信息

介绍 g 对象是因为后面我们在中间件中可以用到一些信息,这些信息的传递就可以通过 g 对象的方式来操作。

以下是 g 对象的赋值与取值操作:


from flask import gg.user_id = 1print(g.user_id)

在这里,我将所有需要给 g 对象赋值的数据都在一个函数里完成,这里,我创建了一个文件:app/utils/init_g_object.py

其中内容如下:

from flask import g, request, sessiondef init_g_object(app):@app.before_requestdef init_g_object_info():g.request_path = request.pathg.user_id = session.get("user_id")g.ip_address = request.remote_addr

g 对象数据的初始化在 app/__init__.py 中:

# app/__init__.pyfrom app.utils.init_g_object import init_g_objectdef create_app():app = Flask(__name__)init_g_object(app)return app

4、Flask 中间件使用实例

这里给两个中间件使用的实例,一个中间件做登录验证操作,一个做接口的日志记录

分别在 app/utils/middlewares/ 文件夹下创建两个文件,login_required_middleware.py 和 request_log_middleware.py

其内容如下:

# login_required_middleware.pyfrom flask import g
from app.utils.exception_handler import UserExceptionclass LoginRequiredMiddleware:def check_login(self):return True if g.user_id is not None else Falsedef check_login_essential(self):url_path = g.request_pathouter_url_list = ["/user/login", "/user/register"]return True if url_path not in outer_url_list else Falsedef check(self):need_check = self.check_login_essential()if need_check:if not self.check_login():raise UserException(code=-1, msg="not login", http_code=401)

在这个中间件中,我们先判断当前请求的路径是否是需要登录才可访问的,如果是,则判断 g 对象中是否有登录信息,也就是 user_id,这个在前面给 g 对象初始化信息的时候有写入

如果需要登录但是没有登录,则直接返回一个报错信息

请求的日志记录中间件内容如下:

# request_log_middleware.pyimport logging
import time
from flask import glogger = logging.getLogger()class RequestLogMiddleware:def log_info(self):total_time = time.time() - g.start_timelog_info = "request_path: {}, request_user: {}, spend_time: {}, ip_address: {}".format(g.request_path,g.user_id,total_time,g.ip_address,)logger.info(log_info)

这个中间件是在请求处理完成之后的逻辑,在这个中间件中,我们直接根据当前时间减去 g 对象的开始时间,这个字段下面会有定义,是在请求开始前写入的,然后将请求路径,请求用户,总耗时,和请求的 IP 地址写入日志。

如果有需要,还可以将请求参数和返回参数也写入日志,方便之后的查询

然后在 middlewares.py 中定义:

# app/utils/middlewares/middlewares.pyfrom .login_required_middleware import LoginRequiredMiddleware
from .request_log_middleware import RequestLogMiddleware
from flask import g
import timedef register_middleware(app):@app.before_requestdef record_start_time():g.start_time = time.time()@app.before_requestdef login_required():LoginRequiredMiddleware().check()@app.after_requestdef request_log_info(response):RequestLogMiddleware().log_info()return response

在中间件的注册中,因为后面的日志记录需要用到请求开始的时间,所以这里定义了一个 record_start_time() 函数,用于记录开始时间,方便后面计算总时长。

5、before_request 中的返回

这里有一点需要注意下,所有被 @app.before_request 装饰的函数,如果有返回值,那么则直接返回,不再接着往后面执行逻辑,比如下面的:

def register_middleware(app):@app.before_requestdef test_return():return {"msg": "test return"}@app.before_requestdef test2():pass@app.after_requestdef test3(response):return response@app.after_requestdef test4(response):return response

在这里,before_request 的顺序执行的,先执行 test_return() 再执行 test2(),但是因为 test_return() 有返回值,所以整个请求流程直接结束了

而对于 after_request 修饰的函数,它是逆序执行的,也就是先执行 test4(),再执行 test3()

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

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

相关文章

Qt6学习笔记:对象树

使用QObject及其子类创建的对象是以对象树的形式来组织的。创建一个QObject对象时若设置一个父对象,它就会被添加到父对象的子对象列表里,一个父对象被删除时,其全部的子对象都会自动删除。QObject类的构造函数里有一个参数用于设置对象的父对…

CommonJS 和 ES6 Module:一场模块规范的对决(上)

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…

【自学笔记】01Java基础-02java基础语法-02变量、对象与类

1 变量、对象、类 变量: 变量是在编程中用来存储数据的占位符,它具有名称和值。在程序执行过程中,变量的值可以改变。根据作用域和生命周期的不同,变量可分为全局变量、局部变量、类变量(静态变量)、实例变…

五、书写规则

目录 一、规则举例 三、在规则中使用通配符 四、文件搜寻 五、伪目标 六、多目标 七、静态模式 八、自动生成依赖性 规则包含两个部分,一个是依赖关系,一个是生成目标的方法。 在 Makefile 中,规则的顺序是很重要的,因为&a…

python 数据容器

数据容器概念 一个可以存储多个元素的python数据类型 python有的数据容器 list(列表) tuple(元组) str(字符串) set(集合) dct(字典) 列表 python的列表的数据类型可以是不同的 my_list ["1",123,True,[123,"3333",d,False]]for item in my_list:p…

【uniapp】多规格选择

效果图 VUE <template> <view><view class"wp-80 pd-tb-40 mg-auto"><button type"warn" click"showDrawer(showRight)">筛选</button></view><!-- 筛选-uni-drawer --><uni-drawer ref"s…

Android debug带系统签名

期望是运行直接带系统签名。 gradle 的 android 目录下&#xff1a; signingConfigs {debug {storeFile file("../signAPK/**.jks")storePassword ******keyAlias ******keyPassword ******}release {storeFile file("../signAPK/**.jks")storePassword **…

暗光增强——Zero-DCE网络推理测试

目录 一、Zero-DCE方法1.1 网络优点1.2 网络适用场景1.3 网络不适用场景 二、源码包三、测试四、测试结果五、推理速度六、总结 一、Zero-DCE方法 Zero-DCE&#xff08;Zero-Reference Deep Curve Estimation&#xff09;是一种用于低光照增强的网络。 1.1 网络优点 无需参考…

ClickHouse数据库详解和应用实践

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 概述1.适用场景2.不适用场景 一、核心特性1.完备的DBMS功能2.列式存储与数据压缩 二、安装部署1.在线安装2.离线安装 三、jdbc访问总结 概述 ClickHouse 是一个用于…

你是唯一的 uniq

文章目录 你是唯一的 uniq语法默认无参数统计出现频次仅仅显示重复的行仅仅显示不重复的行更多信息你是唯一的 uniq Linux uniq 命令用于检查及删除文本文件中重复出现的行列,一般与 sort 命令结合使用。 官方定义为: uniq - report or omit repeated lines uniq 可检查文本…

wordpress在界面将站点地址直接修改为https导致上不去问题的解决办法

wordpress在界面将站点地址直接修改为https导致上不去问题的解决办法 #修改数据库yz_options

计算机网络——OSI参考模型

1. OSI模型的基本概念 1.1 定义 OSI&#xff08;开放式系统互联&#xff09;模型是一个用于理解和标准化电信系统或计算机网络功能的概念性的框架&#xff0c;用于描述和标准化不同计算机系统或网络设备间通信的功能。 1.2 OSI模型的性质 这个模型由国际标准化组织&#xff08…

StartAI 生图关键词整理 第一期

最近很多小伙伴向小编反馈“StartAI生图效果很差”&#xff0c;“效果不好”...... AI生图的关键在于是否投喂合适的关键词。往往好的创意需要好的词汇去润色~ 小编立刻决定给小伙伴们整理生图关键词&#xff01;&#xff01;&#xff01;&#xff01; 一、生成菠萝的创意切面…

数据结构之哈希——学习笔记

今天看网课学习了哈希的数据结构&#xff0c;写下这一篇博客记录自己的学习过程。 1.哈希简介&#xff1a; 我们发现某些时候映射到小集合的时候会同时有多个值映射到一个下标里面&#xff0c;所以接下来是这种情况的解决方案1&#xff1a; 我们考虑当两个数字映射之后的结果…

FastDFS

docker 安装 1拉取镜像&#xff08;已经内置Nginx&#xff09; docker pull delron/fastdfs 2 构建Tracker # 22122 > Tracker默认端口 docker run --nametracker-server --privilegedtrue -p 22122:22122 -v /var/fdfs/tracker:/var/fdfs -d delron/fastdfs tracker 3 …

【ESP32接入语言大模型之通义千问】

1. 通义千问 讲解视频&#xff1a; ESP32接入语言大模型之通义千问 随着人工智能技术的不断发展&#xff0c;自然语言处理领域也得到了广泛的关注和应用。通义千问由阿里云开发&#xff0c;目标是帮助用户获得准确、有用的信息&#xff0c;解决他们的问题和困惑&#xff0c;也…

数据库 补充 树,红黑树,b树,b+树

01.树 02.二叉树和二叉平衡树 03.平衡二叉树的恢复 将导致不平衡的结点称作被破坏者&#xff0c;破坏了结点的平衡的结点成为破坏者&#xff0c;经过调整可以让该树平衡的结点称为调整结点。 LL型&#xff1a; 以被破坏者的左孩子结点作为调整结点&#xff0c;对其进行右旋…

C# Attribute特性实战(1):Swtich判断优化

文章目录 前言简单Switch问题无参Swtich方法声明Swtich Attribute声明带有Swtich特性方法主方法结果 有参Switch修改代码修改运行过程运行结果 总结 前言 在经过前面两章内容的讲解&#xff0c;我们已经简单了解了如何使用特性和反射。我们这里解决一个简单的案例 C#高级语法 …

WPF美化ItemsControl1:不同颜色间隔

首先我们有的是一个绑定好数据的ItemsControl <ItemsControl ItemsSource"{Binding Starts}"> </ItemsControl> 运行后呢是朴素的将数据竖着排列 如果想要数据之间有间距&#xff0c;可以使用数据模板&#xff0c;将数据放到TextBlock中显示&#xff0…

Flutter PageView属性说明

属性说明scrollDirection滑动反向 Axis.vertical上下滑动 Axis.horizontal左右滑动reverse是否反转 true从最后一个记0controllerPageController见下文physics滚动方式pageSnapping是否有回弹效果onPageChanged监听切换children子组件dragStartBehavior处理拖拽开始行为方式 p…