FastAPI 设计溯源:从 Django、Flask 到 Starlette 的替代方案、灵感来源与架构取舍全景解读
【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi
FastAPI并非凭空诞生,它的每一个核心特性——基于 Python type hints 的校验、自动化的 OpenAPI 文档、依赖注入、高性能 ASGI 运行时——都能在它之前的十余个框架、库与工具中找到源头。本文以官方文档 docs/hi/docs/alternatives.md(英文原文见 docs/en/docs/alternatives.md)为主线,逐一拆解 FastAPI 的"前身工具谱系"、它所借鉴的设计思想、以及它最终选择建立在Pydantic + Starlette + Uvicorn之上的底层原因,并结合本仓库源码给出可验证的实现证据。
引言:为什么 FastAPI 会存在
如果没有其他人此前的积累,FastAPI就不会存在。在决定"亲手造一个框架"之前,作者用了很多年时间回避这件事——他先是尝试用各种框架、插件和工具的组合,去解决 FastAPI 如今覆盖的全部能力(数据校验、序列化、自动文档、高性能、依赖注入……)。
直到某一天,除了"从过去工具中取最好的想法、用此前甚至不存在的语言能力(Python 3.6+ 的 type hints)把它们以最佳方式组合起来"之外,已经别无选择。理解这条"从组合到自研"的演进路径,是理解 FastAPI 全部设计取舍的钥匙。
下面按官方文档的顺序,把这条路径上的每一个"站点"过一遍。
一、此前工具的谱系:FastAPI 借鉴了什么
Django:成熟全能框架的两面性
Django 是最流行、被广泛信赖的 Python 框架,曾被用来构建 Instagram 这类系统。但它与关系型数据库(MySQL、PostgreSQL)耦合较紧,想用 NoSQL 数据库(Couchbase、MongoDB、Cassandra 等)作为主存储引擎并不容易。
更重要的是定位差异:Django 生来是在后端渲染 HTML,而不是为现代前端(React、Vue.js、Angular)或 IoT 设备等外部系统提供 API。FastAPI从中看到的启示更多是"反面教材"——一个 Web 框架不必把 HTML 渲染、用户管理等能力全部内置。
Django REST Framework:自动 API 文档的启蒙者
Django REST Framework(DRF)是在 Django 之上构建 Web API 的灵活工具包,被 Mozilla、Red Hat、Eventbrite 等公司使用。它是"自动 API 文档"最早的示范之一,也正是触发作者"寻找 FastAPI"的第一个想法。
值得记住的一条人物线索:DRF 由 Tom Christie 创建,而 Starlette 与 Uvicorn 同样出自他手——这两者正是 FastAPI 的地基。
FastAPI 借鉴点:提供自动生成 API 文档的 Web 用户界面。
Flask:微框架哲学的直接继承者
Flask 是"microframework",不带数据库集成,也不带 Django 默认内置的众多功能。这种简洁与灵活性恰恰允许你用 NoSQL 当主存储;同时它学习曲线平缓,常用于那些并不真正需要数据库、用户管理等开箱即用特性的应用。
文档明确指出:部件解耦 + 可精确扩展的微框架,是作者"想要保留的关键特性"。基于 Flask 的简洁,它很适合构建 API,于是下一步自然是寻找"Flask 版的 Django REST Framework"。
FastAPI 借鉴点:
- 做一个微框架,让所需工具与部件可以自由 mix and match;
- 拥有简单易用的路由系统。
Requests:客户端 API 风格反向塑造服务端 API
FastAPI 并不是 Requests 的替代品——两者作用域完全不同,在 FastAPI 应用内部使用 Requests 反而是常见操作。Requests 是调用API(客户端)的库,FastAPI 是构建API(服务端)的库,分处互补的两端。
Requests 的设计简单直观、默认值合理、开箱即用,同时强大且可定制,也因此成为有史以来下载量最高的 Python 包之一。看这两段代码的对称性:
response = requests.get("http://example.com/some/url")@app.get("/some/url") def read_url(): return {"message": "Hello World"}requests.get(...)与@app.get(...)的相似性并非巧合。在 FastAPI 源码中,这些 HTTP 方法确实是直接以装饰器形式暴露在应用与路由上的,例如 fastapi/routing.py 中api_route、get、post、put、delete等路径操作方法。
FastAPI 借鉴点:
- 简洁直观的 API;
- 直接用 HTTP 方法名(操作)声明端点,直白不绕弯;
- 有合理的默认值,又保留强大的定制能力。
Swagger / OpenAPI:拥抱开放标准而非私有 Schema
作者从 Django REST Framework 想拿走的核心能力是自动 API 文档。随后他发现业界已有用 JSON(或 YAML)描述 API 的标准Swagger,且 Swagger 的 Web 用户界面早已存在——只要能生成 Swagger 文档,就能自动套用这套 UI。
后来 Swagger 被交给 Linux Foundation 并更名为OpenAPI:因此聊 2.0 版本时习惯叫 "Swagger",3+ 版本则称 "OpenAPI"。
FastAPI 借鉴点:为 API 规范采用开放标准(而非自定义 schema),并集成基于标准的 UI 工具——Swagger UI与ReDoc。选择二者是因为足够流行与稳定;事实上针对 OpenAPI 还有数十种其它界面可直接与 FastAPI 搭配使用。
Flask REST frameworks:放弃的原因
市面上有多个 Flask REST 框架,但作者投入时间调研后发现:许多已经停止维护或被废弃,且存在大量未解决的关键 issue,因此无法胜任。
Marshmallow:用代码而非特设类定义 Schema
API 系统两个核心需求之一叫数据"serialization(序列化)":把 Python 对象(比如来自数据库的数据、datetime对象)转换成能走网络的形式。另一个核心需求是数据校验:确认某字段确实是int而非任意字符串——这对外部传入数据尤其重要,没有校验系统就得手写所有检查。
Marshmallow 正是为这两点而生,作者此前大量使用过它。但它诞生于 Python type hints 出现之前,定义每个 schema 必须借助它提供的专属 utils 与 classes。
FastAPI 借鉴点:用代码定义 "schemas",让它自动提供数据类型与校验。
这也直接解释了为何 FastAPI 选择 Pydantic——见下文第三部分。
Webargs:请求数据的自动解析与校验
API 的另一个核心需求是从入站请求中parsing(解析)数据。Webargs 专门在 Flask 等多个框架之上提供这一点,底层用 Marshmallow 做校验,且出自同一批开发者。
FastAPI 借鉴点:对入站请求数据做自动校验。
APISpec:文档缺失的补课,但引入了"字符串内嵌语法"问题
Marshmallow 与 Webargs 以插件形式解决了校验、解析与序列化,但文档仍缺失,于是有了 APISpec。它同样是多框架(含 Starlette)的插件:做法是在每个处理路由的函数 docstring 里用 YAML 书写 schema 定义,再由它生成 OpenAPI schema。
问题也随之而来:YAML 是嵌在 Python 字符串里的"微语法",编辑器难以提供帮助;一旦改了参数或 Marshmallow schema 却忘记同步改 docstring,生成的 schema 就会过期。这是 FastAPI 明确要避免的陷阱——因此它坚持"单一事实来源":从同一份类型声明同时产出校验、序列化与文档。
FastAPI 借鉴点:支持 OpenAPI 这一 API 开放标准。
Flask-apispec:作者此前的"心头好"与它的上限
Flask-apispec 把 Webargs、Marshmallow、APISpec 串成一个 Flask 插件,用 Webargs/Marshmallow 的信息经由 APISpec 自动生成 OpenAPI schema,解决了"在 Python docstring 里手写 YAML"的问题。作者评价它"被严重低估",并指出 Flask + Flask-apispec + Marshmallow + Webargs 是他构建 FastAPI 前最喜欢的后端组合。
这一组合还催生了多个 Flask full-stack generators,而这些生成器后来正是FastAPI项目生成器(对应文档 docs/en/docs/project-generation.md)的前身。
FastAPI 借鉴点:从同一份定义序列化与校验的代码中,自动生成 OpenAPI schema——这正是 FastAPI + Pydantic 的核心机制。
NestJS(与 Angular):编辑器支持与依赖注入的参照系
NestJS 甚至不是 Python——它是受 Angular 启发的 JavaScript/TypeScript NodeJS 框架。它能做到与 Flask-apispec 类似的事情,并拥有受 Angular 2 启发的内置依赖注入系统,但要求预先注册 "injectables",带来一定的啰嗦与代码重复。
参数用 TypeScript 类型描述让编辑器支持相当好;可 TypeScript 类型在编译为 JavaScript 后不复存在,无法仅靠类型同时定义校验、序列化与文档,于是不得不在大量位置叠加装饰器,代码相当冗长;它对嵌套模型的处理也不佳——请求 JSON body 内部再有嵌套 JSON 对象时,难以被正确文档化与校验。
FastAPI 借鉴点:
- 用 Python 类型换取出色的编辑器支持;
- 拥有强大的依赖注入系统,并想办法把代码重复降到最低。
Sanic:基于 asyncio 的高性能先驱
Sanic 是最早一批基于asyncio的极速 Python 框架之一,形态上刻意接近 Flask。技术细节在于它使用uvloop替代 Python 默认的asyncioloop——这正是它快的原因,也启发了 Uvicorn 与 Starlette。
FastAPI 借鉴点:寻找获得惊人性能的路径。这正是 FastAPI 选择基于 Starlette 的原因——按第三方 benchmark 测试,Starlette 是可用的最快框架。
Falcon:request/response 双参数设计带来的局限
Falcon 是另一个高性能 Python 框架,设计上追求极简,并作为 Hug 等框架的地基。它的函数接收两个参数——一个 "request"、一个 "response",从中"读"、"写"数据。这一设计决定了:无法用标准 Python type hints 把请求参数与 body 声明为函数参数,于是数据校验、序列化与文档只能在代码里手写,或另建一层框架(如 Hug)来实现。
FastAPI 借鉴点:获得优秀性能的方法;同时它与 Hug(Hug 基于 Falcon)共同启发了 FastAPI 在函数中声明
response参数——在 FastAPI 中该参数是可选,主要用于设置 headers、cookies 与替代状态码。
Molten:类型驱动思想的早期同路人
作者在构建 FastAPI 初期发现了 Molten,二者想法相当接近:基于 Python type hints、由类型派生校验与文档、带依赖注入系统。差异在于:
- Molten 不用 Pydantic 这类第三方校验库而是自带实现,导致数据类型定义不易复用;
- 配置更冗长,且基于 WSGI(而非 ASGI),无法享受 Uvicorn、Starlette、Sanic 提供的高性能;
- 依赖注入要求预注册,且按声明类型解析,无法为同一类型声明多个提供者;
- 路由集中在一处声明、调用别处定义的函数(而非紧贴端点的装饰器),更接近 Django 而不是 Flask/Starlette 的做法,人为拆散了本应紧耦合的代码。
FastAPI 借鉴点:用模型属性的 "default" 值表达数据类型的额外校验——这改善了编辑器支持,且当时 Pydantic 并不具备。该想法后来甚至反向推动了 Pydantic 更新,如今这部分能力已全部内置于 Pydantic。
Hug:type hints 声明参数的先行者
Hug 是最早用 Python type hints 声明 API 参数类型的框架之一,尽管它用的是自定义类型而非标准 Python 类型,仍是巨大进步;它也是最早为整个 API 生成 JSON 自定义 schema 的框架之一。不过它并不基于 OpenAPI / JSON Schema 这类标准,与 Swagger UI 等工具集成并不直接。它还具备罕见的特性:同一框架既能构建 API 也能构建 CLI。由于它基于 WSGI(同步 Python Web 框架的旧标准),无法处理 WebSocket 等场景,尽管性能同样出色。
人物注记:Hug 由 Timothy Crosley 创建,他同时也是
isort的作者。FastAPI 借鉴点:Hug 启发了 APIStar 的部分设计;它推动 FastAPI 用 Python type hints 声明参数、自动生成定义 API 的 schema,并在函数中声明
response参数以设置 headers 与 cookies。
APIStar(<= 0.5):FastAPI 的"精神前身"
在决定构建 FastAPI 前不久,作者发现了 APIStar server——它几乎具备他寻找的一切且设计出色:是较早用 Python type hints 声明参数与请求的框架实现之一(早于 NestJS 与 Molten),并且采用了 OpenAPI 标准;能基于同一套 type hints 做数据校验、序列化与 OpenAPI schema 生成。但 body schema 更接近 Marshmallow 风格,编辑器支持不算最好。
彼时 APIStar 的 benchmark 是最优的(仅被 Starlette 超越);最初没有自动文档 UI,但作者清楚可以接入 Swagger UI;它拥有依赖注入系统,但同样要求预注册组件;并且缺少 security 集成,作者始终无法在完整项目中替换掉 Flask-apispec 全栈方案。
随后项目焦点转移:它不再是 API Web 框架(作者需聚焦 Starlette),今天 APIStar 是校验 OpenAPI 规范的工具集而非 Web 框架。
人物注记:APIStar 同样出自 Tom Christie——Django REST Framework、Starlette(FastAPI 的底座)、Uvicorn(Starlette 与 FastAPI 的运行服务器)的同一作者。
FastAPI 借鉴点:让它存在。用同一套 Python 类型同时声明数据校验、序列化与文档、且自带出色编辑器支持——这个想法是 FastAPI 的灵魂。APIStar 停更后,Starlette 成为新的、更好的地基,这也是构建 FastAPI 的最终灵感。作者将 FastAPI 视为 APIStar 的 "spiritual successor",在吸收上述所有工具经验的基础上改进并扩展了特性、类型体系与其余部件。
二、FastAPI 脚下踩的三块基石
如果说上一部分是"曾经走过、最终舍弃的路",这一部分则是 FastAPI 最终"选择站在谁的肩膀上"。
Pydantic:数据校验、序列化与 JSON Schema
Pydantic 是基于 Python type hints 定义数据校验、序列化与文档(JSON Schema)的库,因此极其直观。它与 Marshmallow 相当,但 benchmark 中更快;且因同样建立在 type hints 之上,编辑器支持出色。
FastAPI 用它处理全部数据校验、数据序列化与基于 JSON Schema 的模型自动文档化,再把 JSON Schema 数据连同其它能力一起汇入 OpenAPI。仓库层面可以印证这一依赖:在 pyproject.toml 中dependencies显式声明了pydantic>=2.9.0;FastAPI 的所有请求/响应模型解析、校验错误处理均围绕 Pydantic 模型体系展开(如 tests 目录中大量test_validate_response*.py、test_response_model*.py用例)。
Starlette:ASGI 微框架地基
Starlette 是轻量级ASGI框架/工具包,天生适合构建高性能 asyncio 服务,设计上易于扩展、组件模块化。文档列出它的能力清单:
- 相当出色的性能;
- WebSocket 支持;
- 进程内后台任务;
- 启动与关闭事件;
- 基于 HTTPX 的 TestClient;
- CORS、GZip、Static Files、流式响应;
- Session 与 Cookie 支持;
- 100% 测试覆盖率与 100% 类型注解代码库、依赖极少。
Starlette 提供全部基础 Web 微框架功能,但不提供自动数据校验、序列化或文档——这正是 FastAPI 叠加在其上的主要价值(全部基于 type hints + Pydantic),外加依赖注入、安全工具、OpenAPI schema 生成等。
技术细节:ASGI 由 Django core team 成员推动发展,虽尚未成为 Python 标准(PEP),但已被众多工具当作事实标准使用,大幅提升了互操作性——例如可将 Uvicorn 换成 Daphne、Hypercorn 等任意 ASGI server,或接入
python-socketio等 ASGI 兼容工具。FastAPI 用 Starlette 处理全部核心 Web 部件,并在其上叠加特性。代码层面可直接验证:在 fastapi/applications.py 第 42 行,
class FastAPI(Starlette)——FastAPI 应用类直接继承自 Starlette。这意味着"凡是 Starlette 能做的,FastAPI 都能直接做",它本质上就是"加了料的 Starlette"。
Uvicorn:闪电般的 ASGI 服务器
Uvicorn 是基于 uvloop 与 httptools 构建的高速 ASGI server。它不是框架——例如不提供按路径路由的能力,那由 Starlette(或 FastAPI)这类框架在上层提供。Uvicorn 是运行 Starlette 与 FastAPI 应用的推荐服务器,也内置在仓库的依赖与 CLI 中(pyproject.toml 的uvicorn[standard]依赖,以及fastapi/cli.py、fastapi/__main__.py提供的命令行入口)。
FastAPI 将 Uvicorn 作为运行应用的主 Web server,并可通过
--workers命令行参数获得异步多进程能力。更多细节见 Deployment 部署章节。
三、性能与基准:三者关系如何理解
Uvicorn、Starlette 与 FastAPI 三者的层级关系常被混淆:Uvicorn 是 ASGI 服务器、Starlette 是 ASGI 框架/工具包、FastAPI 是在 Starlette 之上叠加数据校验与文档能力的应用框架。要理解、比较并看清三者的差异,官方文档指向了专门的 Benchmarks 基准章节(英文原版见 docs/en/docs/benchmarks.md)。
结合本文第一部分可以看到清晰的传承链:Sanic 用 uvloop 证明"Python 也可以极快"→ 启发 Uvicorn 与 Starlette → 作者在考察了 Django REST Framework、Flask-apispec、APIStar 等一整套方案后,最终选择"基于 Starlette 加 Pydantic 的 FastAPI"——用星标式的一句话概括,即:从过去的工具里取回正确的想法,用 type hints 这一新语言能力把它们整合成单一、可自动化的栈。
结语:一份可复用的"框架选型检查清单"
回看整个谱系,FastAPI 对每个前身工具的关注点其实高度收敛,可以归纳成一张评估"Web API 框架"的通用清单,这也是阅读 docs/hi/docs/alternatives.md 最有价值的产出:
- 是否基于(或兼容)开放标准:Swagger/OpenAPI 取代自定义 schema 是文档与工具生态打通的前提;
- 声明是否只有单一事实来源:docstring 内嵌 YAML(APISpec 路线)必然面临"改代码忘改文档"的过期问题;
- 类型是否贯穿编译/运行期:TypeScript 类型编译后消失,导致 NestJS 需大量装饰器补偿;Python type hints 在运行期保留,得以同时驱动校验、序列化与文档;
- 运行时是否面向未来:WSGI 系(Molten、Hug)难以覆盖 WebSocket 等高阶能力,ASGI 系(Starlette)才有完整异步生态;
- 依赖注入是否零预注册:预注册组件(NestJS、Molten、APIStar)带来代码重复,FastAPI 用"类型即契约"的声明式方案规避;
- 性能是否经第三方验证:从 Sanic 的 uvloop 到 Starlette,性能是框架选型中可被 bench mark 实证的硬指标;
- 嵌套模型能否被正确文档化与校验:这是 NestJS 等框架的短板,也是 FastAPI 依托 Pydantic 递归模型能力的优势所在。
最终,FastAPI 选择站在Pydantic(类型驱动的校验/序列化/JSON Schema)+ Starlette(ASGI 微框架地基)+ Uvicorn(ASGI 服务器)之上——正如仓库源码所证实的那样,FastAPI类直接继承Starlette(fastapi/applications.py),而starlette与pydantic被列为最核心的运行时依赖(pyproject.toml)。理解了这条从 Django 一路延伸而来的"灵感与替代"脉络,你也就理解了 FastAPI 为什么长成今天的样子。
【免费下载链接】fastapiFastAPI framework, high performance, easy to learn, fast to code, ready for production项目地址: https://gitcode.com/GitHub_Trending/fa/fastapi
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考