☰
AI全栈实战 | 3.7-01 Flask:几十行代码徒手造一个 Web 框架,才知道“微“字的分量
2026/10/8 18:40:54 网站建设 项目流程

很多学过 Spring Boot 的人第一次打开 Flask 文档,心里会泛起一个不屑:就这?路由写个装饰器,视图就一个函数,连个自动装配都没有,也能叫框架?

这种反应很真实,但恰恰说明你没看懂 Flask 的"微"。这个"微"字不是"简陋",而是"极简"——它把该有的都留给你,只保留 Web 框架的不可再分的最小本质。这篇我们不急着用 Flask 写 CRUD,而是反向操作:用几十行代码徒手造一个 mini Flask,从"造轮子"里理解一个 Web 框架真正不可删减的东西是什么。

当你亲手把路由表、请求分发、WSGI 这三样搭出来,你再看任何框架(包括 Spring MVC)都会觉得通透——它们都是在同一根骨架上长肉。


一、先定义问题:一个 Web 框架的"最小本质"是什么?

在动手前,先想清楚一个问题:不管 Flask 还是 Spring MVC,一个 Web 框架都必须回答三件事:

  1. URL 如何映射到处理逻辑?(路由)
  2. 请求进来后,怎么把活干完再返回响应?(请求分发 / 生命周期)
  3. 框架如何跟服务器对话?(Web 服务器接口协议)

这三件事,就是框架的"骨架"。其余的一切——模板、ORM 集成、鉴权、配置——都是在这个骨架上"长肉"的可选功能。

明白了这个,你就懂得为什么 Flask 能"微":它只把骨架做扎实,把"长肉"的选择权交给你。这也解释了它为什么有海量扩展——flask-sqlalchemy、flask-login、flask-migrate……每一个都是社区帮你"长好的一块肉",需要哪块装哪块,绝不强塞。


二、徒手造轮子:一个 40 行的 mini Flask

我们一步步来。第一步,路由注册 + 视图函数——这是 Flask 最迷人的设计:用装饰器把 URL 和函数绑定。

# mini_flask.py —— 核心骨架classMiniFlask:def__init__(self):self.routes={}# 路由表:{路径: 处理函数}defroute(self,path):"""装饰器:把一个函数注册到指定路径"""defdecorator(func):self.routes[path]=funcreturnfuncreturndecoratordefdispatch(self,path):"""请求分发:根据路径找到处理函数并调用"""handler=self.routes.get(path)ifhandlerisNone:return"404 Not Found",404returnhandler()

使用起来,已经和 Flask 有七八分神似了:

app=MiniFlask()@app.route("/")defindex():return"<h1>Hello from mini Flask!</h1>"@app.route("/about")defabout():return"这是关于页"# 手动模拟一次请求分发print(app.dispatch("/"))# <h1>Hello from mini Flask!</h1>print(app.dispatch("/nope"))# 404 Not Found

看看这个装饰器做了什么:它让"URL 和函数的关系"从"配置里写死的映射表"变成了"函数旁边紧挨着一个注解"。Spring 的@RequestMapping、Flask 的@app.route本质都是这件事——用一个声明式的标记,把路由信息"贴"在函数上,框架扫一遍就能建好路由表。这正是你在 1.2-03 学的注解/装饰器 = 元数据编程的活学活用。


三、让 mini Flask 跑在真实服务器上:认识 WSGI

光能dispatch还不够,真正的 Web 框架要能被服务器调用。这里有个概念必须搞清:Python 的 Web 框架和 Web 服务器(Gunicorn、uWSGI、开发服务器)是通过一个标准协议对话的——WSGI。

WSGI 规定:你的应用是一个可调用对象,接收两个参数(environ, start_response):

defapplication(environ,start_response):# environ: 一个 dict,装着所有请求信息(PATH_INFO、QUERY_STRING...)# start_response: 一个函数,用来发送响应状态行和响应头start_response("200 OK",[("Content-Type","text/html; charset=utf-8")])return[b"<h1>Hello WSGI!</h1>"]# 任意符合 WSGI 的服务器都能直接驱动这个 application

为什么需要这个标准?想象一下:如果没有 WSGI,每个框架都得自己实现 HTTP 服务器。有了 WSGI,框架只管实现application,服务器只管驱动 WSGI 应用——两者解耦,任意组合。这跟 Java 里 Servlet 规范让 Tomcat 和 Web 应用解耦是同一个道理,规范是生态繁荣的地基。

给我们的 mini Flask 接上 WSGI,让它能被 Gunicorn 驱动:

frommini_flaskimportMiniFlask app=MiniFlask()@app.route("/hello/<name>")# 支持路径参数defhello(name):returnf"<h1>Hello{name}!</h1>"# 更真实的分发:解析路径参数importreclassMiniFlaskWSGI(MiniFlask):def__call__(self,environ,start_response):path=environ["PATH_INFO"]handler,args=self.match(path)# 简化:用正则从路径取参数body=handler(*args)ifhandlerelse"404"status="200 OK"ifhandlerelse"404 Not Found"start_response(status,[("Content-Type","text/html; charset=utf-8")])return[body.encode("utf-8")]# 现在 `app` 就是一个符合 WSGI 的应用,gunicorn 可以直接驱动

到这一步,你的 mini Flask 已经能:

  • ✅ 用装饰器注册路由
  • ✅ 解析路径参数(/hello/<name>)
  • ✅ 实现 WSGI 协议,能被标准服务器驱动

这就是一个 Web 框架不可再删减的全部骨架。你现在去看真实 Flask 的源码,会发现它的核心(Flask.add_url_rule、Flask.dispatch_request、wsgi_app)就是在这些基础上做到工程级完善——加上了上下文(context)、错误处理、请求/响应对象封装、蓝图等等。


四、从 mini 到真 Flask:多出来的都是"便利层"

我们造的轮子能跑,但真实项目里你还想要很多便利,真实 Flask 正是这样一层层加厚的:

mini Flask 缺什么真实 Flask 怎么补解决什么问题
每个请求都要手动传参数请求上下文request视图函数里直接用request.args、request.form
全局状态会串应用上下文 + 请求上下文隔离同一个 app 服务多请求不串数据
代码全堆一个文件蓝图 Blueprint按模块拆分路由,对应 Spring 的 Controller 分包
无数据库flask-sqlalchemy扩展一个扩展接入 ORM
无登录flask-login扩展一个扩展搞定会话登录

看下蓝图怎么救活你的项目结构——这是从"demo"迈向"工程"的关键一步:

# blueprints/user.pyfromflaskimportBlueprint user_bp=Blueprint("user",__name__)@user_bp.route("/users")deflist_users():return"用户列表"# app.py —— 注册蓝图fromflaskimportFlaskfromblueprints.userimportuser_bp app=Flask(__name__)app.register_blueprint(user_bp,url_prefix="/api")# 挂到 /api 前缀下

蓝图的意义和 Java 的Controller 分包 +@RequestMapping前缀一模一样:把不同业务模块的路由隔离,再统一挂载到主应用。理解了蓝图,你就理解了所有框架"模块化路由"的设计动机。

而请求上下文(context)是 Flask 最容易被忽视、却最该懂的设计:Flask 允许你在视图里直接from flask import request然后用,是因为它用一个线程/协程局部的 contextvar把"当前这次请求"绑定到了当前执行线程。这样你不用把 request 当参数传来传去——这跟 Spring 把 request 放进 ThreadLocal 再通过依赖注入取到,是异曲同工。


五、微框架的"微"到底好在哪?该不该选 Flask

绕了一圈,回答开篇那个"不屑"。Flask 的"微"带来三个实打实的好处:

  1. 心智负担低:核心就路由+视图+上下文,几天能完全吃透,出 bug 你能看穿整个调用链。
  2. 选型自由:数据库、模板、鉴权都自己挑,不绑定。适合"轻量 API + 自由组装"。
  3. 是绝佳的学习对象:因为它"薄",你能一眼看穿框架本质,反过来帮你看懂更重的框架。

但它不擅长什么?需要一整套"电池"的大型全栈(Admin、ORM、模板、DRF 全家桶)时,Flask 要自己东拼西凑——这时候 Django 的"大而全"更省心。所以选型口诀是:轻量 API / 微服务 / 想掌控一切选 Flask;全家桶 / 快速出后台 / 团队规范统一选 Django。


小结

认知结论
Web 框架最小本质路由 + 请求分发 + 服务器接口协议(WSGI)
装饰器路由的原理注解式声明元数据,框架扫描建路由表
WSGI 是什么框架与服务器的解耦标准,同 Servlet 规范一个道理
Flask 的"微"只做骨架,把长肉(DB/登录/模板)交给扩展
上下文/蓝图的类比对应 Spring 的 ThreadLocal/请求上下文 与 Controller 分包

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询