news 2026/5/1 9:06:01

Flask 的before_request钩子深度详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Flask 的before_request钩子深度详解

1. 他是什么

before_request是 Flask 框架里的一个请求钩子(hook)。可以把它想象成一家餐厅的迎宾员——每当有客人走进餐厅(也就是客户端向服务器发来一个请求),迎宾员都会先一步上前,在客人落座点菜(视图函数执行)之前完成一些固定的接待动作。

在 Flask 里,你用@app.before_request装饰一个函数,这个函数就会在每次请求进入路由、执行视图函数之前被自动调用。

2. 他能做什么

因为before_request跑在业务逻辑之前,而且可以访问请求对象request,所以它很适合处理那些每个请求都需要、但又跟具体业务无关的横切关注点。

  • 身份验证:检查用户是否已登录,如果没登录就直接返回登录页面,不再往下走视图函数。

  • 请求日志:记录每一次请求的路径、来源 IP、耗时等。

  • 设置全局变量:把从数据库里查出的用户信息挂载到g对象上,供视图函数后续使用。

  • 请求预处理:强制要求请求使用 HTTPS,或者统一把 POST 表单里的空格 trim 掉。

  • 限流或黑白名单:在请求到达业务层之前就把非法 IP 拦下。

用一个生活例子:小区门卫。before_request就像门卫,所有访客(请求)进小区前,门卫都会做同一套动作——登记、查健康码、询问房号,做完才放行去找具体住户(视图函数)。

3. 怎么使用

用法非常简单,直接在 Flask 应用实例上注册装饰器。

python

from flask import Flask, g, request, abort app = Flask(__name__) @app.before_request def load_logged_in_user(): # 假设 token 放在请求头里 token = request.headers.get('Authorization') if token: user = verify_token(token) # 自定义的 token 校验函数 g.user = user # 挂载到 g 对象 else: g.user = None @app.before_request def reject_suspicious_ips(): blacklist = ['192.168.1.100', '10.0.0.5'] if request.remote_addr in blacklist: abort(403) # 直接返回禁止访问,不会进视图

如果有多个before_request函数,它们会按照注册顺序从上往下执行。任何一个函数返回了Response对象(或者调用了abort、抛异常),请求流程就会被中断,后面的before_request和视图函数都不会执行。

4. 最佳实践

  • 只放轻量逻辑before_request会增加每个请求的额外耗时。不要把重计算、长时间 I/O 操作放进来,否则整个应用的响应时间都会被拖慢。身份校验查缓存,日志写入用异步或本地队列,不要直接同步写数据库。

  • 区分全局与蓝图:如果只有一部分路由需要某个前置逻辑(比如只有管理后台需要鉴权),应该使用蓝图的before_request,而不是全局的app.before_request。蓝图级别的钩子只对该蓝图下的路由生效,避免污染公共接口。

  • 谨慎修改request对象request在 Flask 里是只读的,不要试图直接赋值request.method = 'GET'。如果需要修改请求数据(例如统一给 JSON body 加字段),可以考虑在钩子里重新封装一个对象挂到g上,而不是篡改原请求。

  • 善用g对象before_request里计算好的数据(如当前用户、请求开始时间戳)可以存到g里,后面的视图函数或after_request都能直接取用,省去重复查询。

  • 异常处理before_request里抛出的异常会走全局异常处理器,所以请确保app.errorhandler能覆盖到钩子里可能抛出的异常类型(例如abort(403))。

5. 和同类技术对比

after_request对比
before_request在请求开始前执行,after_request在视图函数执行完后、响应发给客户端前执行。一个负责进场预处理,一个负责出场包装,分工明确。

与 Django 中间件对比
Django 的中间件是一个更重、更完善的体系,分为process_requestprocess_viewprocess_response等多个阶段,并且可以控制请求在整个处理管道中的流转。
Flask 的before_request只相当于process_request这一阶段,并且只能通过返回Responseabort来截断请求,没有 Django 中间件那种“向前调用”的灵活性。但 Flask 的优势是轻量、直观,学习成本和代码侵入性都更低。

与 Flask 的before_first_request对比
before_first_request只在应用启动后第一个请求进来时执行一次,适合做初始化动作(如加载配置、预热缓存)。而before_request每一次请求都会执行,两者作用范围完全不同,不能混用。

与装饰器方式对比
你也可以写一个自定义装饰器,把它加到需要鉴权的视图函数上。这种方式更精确——只对特定路由生效,但需要显式装饰每个函数,容易遗漏。
before_request则是“全局生效”或“蓝图范围生效”,一劳永逸,适合那些所有接口都必须遵守的规则。如果规则只在部分接口适用,优先考虑蓝图级钩子或自定义装饰器,避免全局钩子误伤公开接口。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/1 4:07:44

如何理解词嵌入的维度?维度越大越好吗?

在学习自然语言处理(NLP)时,很多人都会遇到一个问题: 词嵌入的维度到底是什么意思? 为什么有的模型用 100 维,有的用 300 维,而 BERT 却是 768 维? 维度越大越好吗? 每…

作者头像 李华
网站建设 2026/5/1 4:08:28

SpringBoot打包可执行jar包启动方式:JarLauncher、PropertiesLauncher

文章目录1, 项目结构2, 默认打包可执行jar启动主类:JarLauncher3, 打包可执行jar启动主类:PropertiesLauncher1, 项目结构 springboot-tar-demo/ ├── src/ │ ├── main/ │ │ ├── assembly/ │ │ │ └── assembly.xml # 上述…

作者头像 李华
网站建设 2026/5/1 4:06:51

为什么 UI 半透明面板会出现“黑边”和“发灰”:一篇把你从玄学里拎出来的透明指南

你肯定遇到过这种场面: 你做了个很常见的 UI 弹窗: 背景来一层半透明黑遮罩,弹窗面板是圆角、带柔和透明边缘的 PNG。 在编辑器里一看——哎挺好。 一跑真机——圆角边缘一圈黑线;或者整张面板“发灰”,像蒙了一层雾;再或者跟背景叠一起颜色不对,黑得不干净、灰得不高级…

作者头像 李华
网站建设 2026/5/1 4:06:54

欧盟与印度自贸协定开启IT服务新时代

欧盟与印度达成的首个自由贸易协定可能推动印度IT服务提供商在欧洲大陆扩展业务,为其打开大量未开发的市场机遇。虽然北欧和比荷卢地区等较小经济体集群已经成为印度IT服务公司的成功市场,但在一些更大的经济体中,这些公司仍有巨大的增长空间…

作者头像 李华
网站建设 2026/5/1 4:04:50

Git Worktree + Claude Code:多终端并发开发完全实战

引言:等待 AI 的时间浪费 如果你已经开始使用 Claude Code 进行开发,一定遇到过这样的场景: 场景 1: 让 AI 分析一个复杂的 Bug,你坐在电脑前等了 5 分钟,AI 还在读代码… 场景 2: 让 AI 重构一个大模块,15 分钟过去了,你刷完了朋友圈,AI 还在工作… 场景 3: 临时有个紧急 Bug…

作者头像 李华
网站建设 2026/5/1 4:02:17

1.8 本章小结 记住这3点后面少踩坑

1.8 本章小结:记住这 3 点,后面少踩坑 本节学习目标 把第 1 章内容归纳成三条主线,便于记忆与复述。 明确与第 2 章(技术框架)的衔接点,减少学习断层。 用「少踩坑」清单做自检,避免常见概念与设计错误。 一、三条主线(记住这 3 点) 1. Agent 是什么、和普通程序差在…

作者头像 李华