FastAPI 的设计渊源与选型解析:从 Django、Flask、APIStar 到 Starlette 与 Pydantic 的灵感溯源
FastAPI 并非凭空诞生,而是作者多年间对比 Django、Flask、Requests、NestJS、Sanic、Falcon、Molten、Hug、APIStar 等十余种框架后,将其各自最优思想重新组合的产物。本篇基于仓库中《Alternativen, Inspiration und Vergleiche》(替代品、灵感与对比)文档展开,梳理 FastAPI 的灵感来源、所依赖的核心组件(Pydantic、Starlette、Uvicorn),并结合当前仓库源码印证这些设计决策是如何真正落地的,帮助读者理解 FastAPI “为什么是现在这个样子”。
一、写作背景:为什么需要一个新框架
原文档开宗明义:FastAPI 如果没有他人的先行工作就不会存在。作者在相当长的时间里一直避免创建新框架,而是先尝试用多种现有框架、插件和工具的组合来覆盖 FastAPI 现在所覆盖的全部功能。直到某个节点,他发现没有任何单一工具能同时提供所需的全部能力,于是决定打造一个新框架:
- 吸收此前各类工具中最好的想法;
- 以当时尚不可用的语言特性(Python 3.6+ 类型注解)为地基,把它们组合到最优形态。
这个“组合最佳实践”的思路贯穿整份文档:每个被讨论的工具,最后都会落到一条或多条“FastAPI 从中获得了什么”的结论上。
二、先行工具:FastAPI 从谁那里学到了什么
2.1 Django
Django 是最流行的 Python 框架,拥有极高的信任度,被用于构建 Instagram 这样的系统。但它有两个与 FastAPI 目标定位不同的特点:
- 与关系型数据库(MySQL、PostgreSQL 等)耦合较紧,因此把它换成 NoSQL 数据库(Couchbase、MongoDB、Cassandra 等)作为主存储并不轻松;
- 定位是后端生成 HTML,而不是为现代前端(React、Vue.js、Angular)或 IoT 设备等系统提供 API。
FastAPI 选择了与 Django 相反的取向:不做 HTML 渲染,不做数据库强绑定,专注 API。
2.2 Django REST Framework(DRF)
DRF 是为在 Django 之上构建 Web API 而开发的灵活工具包,被 Mozilla、Red Hat、Eventbrite 等公司使用。它对 FastAPI 最关键的一点贡献是:
它是“自动生成 API 文档”的最早范例之一,也是直接激发 FastAPI 诞生动机的最早想法之一。
值得注意的血缘关系:DRF 的作者是 Tom Christie,他也是 Starlette 和 Uvicorn 的创建者——而 Starlette 与 Uvicorn 正是 FastAPI 的底层基座。FastAPI 从 DRF 继承的核心理念就一条:拥有自动的 API 文档界面。
2.3 Flask:微框架思想的来源
Flask 是一个“微框架”(microframework):不包含数据库集成,也没有 Django 那样默认附带的大量功能。这种简单与灵活性带来了几个好处:
- 可以方便地把 NoSQL 数据库作为主数据存储;
- 由于足够简单,学习曲线直观(虽然文档局部偏技术化);
- 常被用于不需要数据库、用户管理等功能的轻量应用,缺失的能力可用插件补齐。
部件解耦 + 按需扩展 的“微框架”模式,是作者明确表示希望保留的关键特性。FastAPI 从 Flask 获得的启发包括:
- 做一个微框架,让开发者能自由组合所需的工具和部件;
- 提供一个简单、好用的路由系统。
作者当时的实践路径是:先用 Flask 做 API 的骨架,再寻找一个“Flask 版 Django REST Framework”来补齐文档与验证能力——这直接引出了下一节。
2.4 Requests:不是竞品,而是设计范本
FastAPI 其实不是 Requests 的替代品,二者范围完全不同,甚至在 FastAPI 应用内部使用 Requests 才是常态。两者的关系可以概括为:
- Requests 是与 API 交互的客户端库;
- FastAPI 是构建 API 的服务端库;
- 二者处于链条的两端,互为补充。
Requests 的设计被作者反复称道:简单、直观、易用、默认值合理,同时强大且可定制。一个 GET 请求只需一行:
response = requests.get("http://example.com/some/url")
对应的 FastAPI 路径操作(见仓库教程示例 docs_src/first_steps/tutorial001_py310.py)则是:
@app.get("/some/url")
def read_url():
return {"message": "Hello World"}
对照 requests.get(...) 与 @app.get(...),这种对称的直观性不是巧合。FastAPI 从 Requests 借鉴了三点:
- 简单、直观的 API 设计;
- 直接用 HTTP 方法名作为操作入口;
- 合理的默认值 + 强大的可配置能力并存。
2.5 Swagger / OpenAPI:开放标准而非私有格式
作者在向 DRF 要“自动 API 文档”时发现了一个叫 Swagger 的标准:用 JSON(或其超集 YAML)描述 API,并且已经存在可渲染 Swagger 文档的 Web 界面。只要能自动产出 Swagger 描述,就能免费获得这些现成的 UI。
历史脉络:Swagger 后来移交给了 Linux 基金会并更名为 OpenAPI。因此业界习惯称 2.0 版本为 “Swagger”、3.0 及以后为 “OpenAPI”。
FastAPI 的决策是:采用开放标准(OpenAPI)而不是自定义私有 Schema,并集成基于该标准的现成 UI 工具:
- Swagger UI
- ReDoc
这两者因流行且稳定而被选为默认,但用户完全可以替换成其他 OpenAPI 兼容界面。这条设计在源码中可以直接看到:fastapi/openapi/docs.py 提供了 get_swagger_ui_html 与 get_redoc_html 两个函数,分别生成默认的 /docs 和 /redoc 页面,默认从 CDN 加载 Swagger UI 静态资源(swagger-ui-bundle.js),并且对嵌入 <script> 标签的 JSON 做了 <、>、& 的转义处理以防止注入。
2.6 Flask REST 生态:Marshmallow、Webargs、APISpec、Flask-apispec
这一组工具共同回答了一个问题:API 框架到底需要哪些核心能力?
Marshmallow —— 序列化与验证
API 系统的基础需求之一是数据“序列化”(marshalling):把代码中的 Python 数据(例如数据库对象)转换为可通过网络发送的形态(如 JSON 对象、datetime 转字符串)。另一项核心需求是数据验证:确保字段是 int 而不是任意字符串,这对入站数据尤为重要——没有验证系统就只能手工写检查代码。Marshmallow 正是为此而生,且诞生早于 Python 类型注解,定义 Schema 必须使用它自带的工具类和字段类。
FastAPI 从中获得的启发:用代码定义“Schema”,同时自动获得数据类型声明和验证能力——但 FastAPI 选择了用标准 Python 类型注解 + Pydantic 来实现,而不是自定义字段类。
Webargs —— 自动解析入站请求
API 还需要从入站请求中解析(parsing)并转换为 Python 数据。Webargs 为包括 Flask 在内的多个框架提供这一能力,底层复用 Marshmallow 做验证(两者出自同一批开发者)。
FastAPI 的启发:自动验证入站请求数据。
APISpec —— 补上文档这一环
Marshmallow + Webargs 覆盖了验证、解析、序列化,唯独缺文档。APISpec 作为多框架插件(也有 Starlette 插件)补位:在路由函数的 docstring 中用 YAML 写 Schema 定义,然后生成 OpenAPI Schema。
但它引入了一个经典问题:在 Python 字符串里再套一层微语法(大段 YAML)。编辑器几乎帮不上忙;一旦参数或 Marshmallow Schema 变了而忘了同步改 YAML docstring,生成的 Schema 就会过期失真。
FastAPI 的启发:支持 API 的开放标准 OpenAPI(但绝不重蹈“YAML 写在字符串里”的覆辙)。
Flask-apispec —— 组合拳的巅峰
Flask-apispec 是一个 Flask 插件,把 Webargs、Marshmallow 和 APISpec 串起来:利用前两者的信息,通过 APISpec 自动生成 OpenAPI Schema。作者评价它“很棒但被严重低估”,文档过于紧凑抽象可能是它不够流行的原因。它解决了“在 docstring 里写 YAML”的问题。
在 FastAPI 诞生之前,Flask + Flask-apispec + Marshmallow + Webargs 就是作者(以及多个外部团队)的主力后端技术栈,并据此孵化了多个 Flask 全栈生成器项目,而这些全栈生成器后来又成为 FastAPI 项目生成器的基础(参见 项目生成文档)。
FastAPI 从中提炼出的核心思想:从同一份既定义序列化又定义验证的代码,自动生成 OpenAPI Schema——这是整个 FastAPI 设计哲学的总纲。
2.7 NestJS(与 Angular):非 Python 世界的对照
NestJS 是一个受 Angular 启发的 TypeScript/Node.js 框架,不是 Python,但它达到了类似 Flask-apispec 的效果,提供了几个重要参照点:
- 内置依赖注入系统(灵感来自 Angular 2),但要求预先注册“Injectables”——与作者所知的其他 DI 系统一样,造成代码冗长和重复;
- 参数用 TypeScript 类型标注(类似 Python 类型注解),因此编辑器支持相当好;
- 但 TypeScript 类型在编译为 JavaScript 后不会保留到运行时,类型无法同时承担验证、序列化和文档三个职责,于是必须在多处堆叠装饰器,代码变得相当啰嗦;
- 对嵌套模型支持不佳:请求体里嵌套 JSON 对象难以被正确文档化和验证。
FastAPI 的启发:
- 用 Python 类型获得优秀的编辑器支持;
- 具备强大的依赖注入系统,同时最小化代码重复(不做预注册,直接在函数签名声明)。
2.8 Sanic:asyncio 高性能路线的先驱
Sanic 是最早基于 asyncio 的极速 Python 框架之一,设计上刻意贴近 Flask。技术上它用 uvloop 替代了标准 asyncio 事件循环,这让它获得了速度,也直接启发了 Uvicorn 与 Starlette 的实现(后两者在公开基准测试中比 Sanic 更快)。
FastAPI 从 Sanic 得到的启示是:必须找到一条取得卓越性能的路径。因此 FastAPI 选择构建在 Starlette 之上——按第三方基准测试,它是当时最快的框架之一。
2.9 Falcon:两种 API 设计哲学的分野
Falcon 是另一个高性能 Python 框架,风格极简,是 Hug 等框架的底层。它的方法签名是 (request, response) 两个对象:手动从 Request “读”、向 Response “写”。
这个设计带来的直接后果是:无法用标准 Python 类型注解把请求参数和请求体声明为函数参数,数据验证、序列化和文档要么手工写在代码里,要么在 Falcon 之上再盖一层框架(Hug 就是这么做的)。FastAPI 选择了与之正交的另一条路:类型注解即声明。
FastAPI 从 Falcon(连同基于它的 Hug)借鉴的另一点是:在函数中声明一个 response 参数。FastAPI 中该参数是可选的,主要用于设置 Header、Cookie 和替代状态码。在源码中可以直接验证这一点:fastapi/routing.py 的路由处理逻辑中存在 response: Response | None = None 的声明(约第 407 行),端点函数签名里带上 response: Response 时框架会将其注入。
2.10 Molten:类型注解路线的同路人
作者是在 FastAPI 开发早期发现 Molten 的,两者理念高度相似:
- 基于 Python 类型注解;
- 从类型推导验证与文档;
- 依赖注入系统。
但 Molten 有几个与 FastAPI 分道扬镳的地方:
- 不依赖 Pydantic 等第三方数据验证/序列化/文档库,而是自带一套,导致其数据类型定义的可复用性差;
- 需要更繁琐的配置;
- 基于 WSGI 而非 ASGI,无法享受 Uvicorn、Starlette 一类 ASGI 工具链的高性能;
- DI 系统要求预注册依赖,且按声明类型解析,因此无法声明两个提供同一类型的不同“组件”;
- 路由集中在单处声明(用函数引用,而非直接放在处理函数上方的装饰器),更接近 Django 风格,把逻辑上紧密耦合的东西在代码里拆开了。
FastAPI 反过来从 Molten 获益的一点是:允许通过模型属性的“默认值”来附加数据验证声明——这改善了编辑器支持,而且这一做法最终被上游吸收,如今 Pydantic 已原生支持同样的验证声明风格(即 Field(...) 等写法),FastAPI 只是顺势使用。
2.11 Hug:类型注解声明 API 的最早实践者
Hug 是最早用 Python 类型注解声明 API 参数类型的框架之一(尽管用的是自定义类型而非标准 Python 类型),这已经是一个巨大的进步,并启发了包括 APIStar 在内的后续工具。Hug 还是最早生成自定义 JSON Schema 来描述整个 API 的框架之一——但它没有基于 OpenAPI / JSON Schema 标准,因此难以接入 Swagger UI 等生态工具。
Hug 还有一个独特能力:同一框架既能写 API 也能写 CLI。不过它基于 WSGI,不支持 WebSocket 等特性(性能依然不错)。附带一提,Hug 的作者是 Timothy Crosley,他也是 isort(自动排序 import 的工具)的作者。
Hug 对 FastAPI 的具体启发:
- 用 Python 类型注解声明参数,并自动生成定义整个 API 的 Schema;
- 声明
response参数来设置 Header 和 Cookie; - 它本身还启发了 APIStar 的部分设计。
2.12 APIStar(<= 0.5):最接近成品的一次
在决定创建 FastAPI 前不久,作者发现了 APIStar——“几乎拥有他想要的一切,而且设计出色”。它是作者见过的最早一批用 Python 类型注解声明参数和请求的框架实现之一(早于 NestJS 和 Molten),与 Hug 大致同期发现,但 APIStar 用的是 OpenAPI 标准,并且多处基于同一份类型注解实现了自动数据验证、序列化和 OpenAPI Schema 生成。
不足之处:
- 请求体 Schema 定义没有使用与 Pydantic 相同的 Python 类型注解(更接近 Marshmallow 风格),编辑器支持打折扣——但当时它仍是最佳可选项;
- 性能基准当时最好,仅次于 Starlette;
- 最初没有内建文档 Web 界面(作者知道可以自行挂上 Swagger UI);
- DI 系统同样需要预注册组件;
- 没有安全(security)集成,作者本想提 PR 补上,以便用它替换基于 Flask-apispec 的全栈生成器,但项目方向变了。
命运转折:APIStar 的开发者转向了 Starlette,APIStar 不再作为 Web 框架演进,如今它只是一组校验 OpenAPI 规格的校验工具(作者注明此节讨论的是 0.5 及以前版本)。APIStar 的创建者正是 Tom Christie——DRF、Starlette、Uvicorn 的作者。
作者对 FastAPI 的定位一句话总结得最重:
FastAPI 是 APIStar 的“精神续作”(spiritual successor):基于对所有这些先行工具经验的总结,改进并扩展了它的功能、类型系统与其他部分。Starlette 的诞生提供了更好的地基,成了 FastAPI 开发的最后临门一脚。
三、FastAPI 实际使用的组件
灵感归灵感,真正撑起 FastAPI 的是三个组件。这一节可以逐条在仓库源码中对上号。
3.1 Pydantic:验证、序列化、JSON Schema 三位一体
Pydantic 是基于 Python 类型注解定义数据验证、序列化和文档(通过 JSON Schema)的库,因此极其直观。它可比作 Marshmallow,但基准测试中更快,且因为基于同样的类型注解,编辑器支持一流。
FastAPI 用它完成:
- 全部的数据验证;
- 全部的数据序列化;
- 基于 JSON Schema 的自动模型文档——FastAPI 再把这份 JSON Schema 装配进 OpenAPI。
依赖声明可以在 pyproject.toml 中确认:核心依赖为 starlette>=0.46.0 与 pydantic>=2.9.0(另有 typing-extensions、typing-inspection、annotated-doc),而 standard 可选依赖组中还包含 uvicorn[standard]、python-multipart、email-validator 等。
3.2 Starlette:FastAPI 的继承者身份
Starlette 是一个轻量级 ASGI 框架/工具包,专为构建高性能异步服务设计,简单直观、模块化、易扩展。它提供:
- 出色的性能;
- WebSocket 支持;
- 同进程后台任务(Background Tasks);
- Startup / Shutdown 事件;
- 基于 HTTPX 的测试客户端;
- CORS、GZip、静态文件、流式响应;
- Session 与 Cookie 支持;
- 100% 测试覆盖与全类型注解代码库;
- 极少的强依赖。
文档原文称 Starlette 是当时“测试过最快的 Python 框架”,仅次于(并非框架而是服务器的)Uvicorn。它提供微框架的全部基础能力,但不提供自动数据验证、序列化和文档——而这正是 FastAPI 用类型注解 + Pydantic 补上的第一块拼图,其余还包括依赖注入系统、安全工具、OpenAPI 生成等。
这一点在源码中是铁的事实:fastapi/applications.py 中 FastAPI 类直接继承自 Starlette 的同名类:
from starlette.applications import Starlette
...
class FastAPI(Starlette):
"""
`FastAPI` app class, the main entrypoint to use FastAPI.
"""
也就是说,文档里那句“FastAPI 本质上是被加强过的 Starlette”不是比喻——凡是 Starlette 能做的,FastAPI 应用都能直接做。
ASGI 背景:ASGI 是由 Django 核心团队部分成员推动的新标准(文档写作时尚未成为正式 PEP)。它已被多工具当作事实标准使用,显著提升了互操作性:可以把 Uvicorn 换成 Daphne、Hypercorn 等任意 ASGI 服务器,或加入 python-socketio 这类 ASGI 兼容工具。
3.3 Uvicorn:推荐的 ASGI 服务器
Uvicorn 是基于 uvloop 和 httptools 的高性能 ASGI 服务器。它不是 Web 框架——不提供路径路由之类的工具,那是 Starlette(或 FastAPI)的职责。它是 Starlette 和 FastAPI 的推荐运行服务器,支持 --workers 命令行选项以启用多进程异步服务器。部署细节参见 部署文档。
四、把“灵感清单”映射回仓库源码
前面大量“FastAPI 从 X 学到 Y”的结论,都可以在当前仓库中逐一验证,形成一张灵感到实现的对照表:
| 灵感来源 | FastAPI 中的落点 | 仓库内证据 |
|---|---|---|
| DRF 的自动文档 | 默认 /docs(Swagger UI)与 /redoc |
fastapi/openapi/docs.py 的 get_swagger_ui_html / get_redoc_html |
| OpenAPI 开放标准 | 从路由与 Pydantic 模型自动生成 OpenAPI Schema | fastapi/openapi/utils.py 的 get_openapi |
| Flask 微框架 + 直观路由 | @app.get(...) 等路径操作方法 |
fastapi/applications.py、docs_src/first_steps/tutorial001_py310.py |
Requests 的 requests.get 对称设计 |
@app.get("/some/url") 与 requests.get(url) 的镜像命名 |
见第二节 2.4 的代码对照 |
| Falcon / Hug 的 response 参数 | 可选 response: Response 参数用于 Header/Cookie/状态码 |
fastapi/routing.py 的 response: Response | None = None |
| APIStar / Molten / Hug 的类型注解驱动 | 参数注解同时驱动验证、序列化、文档 | pyproject.toml 的 pydantic>=2.9.0 依赖声明 |
| Starlette 微框架基座 | FastAPI(Starlette) 直接继承 |
fastapi/applications.py#L42 |
| Sanic 启发的异步高性能路线 | 依赖 Starlette + Uvicorn 的 ASGI 栈 | pyproject.toml starlette>=0.46.0 及 uvicorn[standard] 可选依赖 |
| 最小化 DI 代码重复(相对 NestJS/Molten/APIStar) | 函数签名内直接声明依赖,无预注册 | fastapi/dependencies/ 目录下的依赖解析实现 |
例如 OpenAPI 生成的入口 get_openapi 在 fastapi/openapi/utils.py,FastAPI 类构造时(fastapi/applications.py)即导入并接线了文档页函数,swagger_ui_default_parameters 中还固化了 deepLinking、showExtensions 等 Swagger UI 默认配置——这些正是“继承 Swagger/OpenAPI 生态”的具体体现。
五、关于性能:Uvicorn、Starlette、FastAPI 的关系
理解三者分层(服务器 / 框架 / 框架之上的 API 层)是读懂 FastAPI 性能问题的关键:
- Uvicorn 是 ASGI 服务器(事件循环层,uvloop + httptools);
- Starlette 是 ASGI 框架(路由、中间件、WebSocket 等);
- FastAPI 是构建在 Starlette 之上、叠加类型注解驱动的验证/文档/DI/安全的 API 框架。
FastAPI 自身并不声称比 Starlette 或 Uvicorn 快,文档原文对此的口径是:选择 Starlette 作为基座,是因为它是第三方基准测试中最快的框架(仅次于作为服务器的 Uvicorn)。三者之间的基准对比与测试方法,仓库内有专门的 Benchmarks 文档,其中说明了如何复现对比 FastAPI 与其他框架的速度差异。
六、小结:FastAPI 是一张“最佳实践拼贴图”
这份文档的价值不在于给出一份竞品横评,而在于交代了 FastAPI 每一块设计积木的来源:
- 从 DRF 继承了“自动 API 文档”这一核心卖点;
- 从 Flask 继承了微框架、可组合、易学的形态;
- 从 Requests 继承了直觉化、对称的 API 风格;
- 从 Swagger/OpenAPI 社区继承了开放标准优先、UI 工具生态复用的策略;
- 从 Marshmallow/Webargs/APISpec/Flask-apispec 继承了“同一份 Schema 定义同时驱动验证、序列化与文档”的哲学,并刻意规避了 YAML-in-docstring 的腐化陷阱;
- 从 NestJS 借了依赖注入的雄心,同时规避了预注册带来的代码重复;
- 从 Sanic/Falcon 确认了高性能异步路线的必要性;
- 从 Molten/Hug 验证了类型注解驱动可行;
- 从 APIStar 得到了临门一脚,并以“精神续作”的姿态站在 Starlette 与 Pydantic 的地基上。
阅读完本篇后,你可以清楚地回答两个问题:FastAPI 的每个标志性特性(自动文档、类型注解验证、response 参数、无预注册的 DI、ASGI 高性能基座)分别是从哪个前辈那里“抄作业”的,以及这些特性在当前仓库的哪些源码文件中得到了实现——这正是理解 FastAPI 设计取舍的最短路径。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00