FastAPI 集成 GraphQL 完整指南:ASGI 原理、Strawberry 实战与旧版 GraphQLApp 迁移
本文以 FastAPI 官方文档《GraphQL》(德语版位于 docs/de/docs/how-to/graphql.md,英文版位于 docs/en/docs/how-to/graphql.md) 为主体,系统讲解如何在 FastAPI 应用中集成 GraphQL:包括基于 ASGI 标准的集成原理、可选 GraphQL 库的对比、推荐方案 Strawberry 的完整集成代码,以及如何把旧版 Starlette GraphQLApp 代码迁移到替代方案。读完后你可以独立完成一个 FastAPI + GraphQL 混合应用的搭建,并理解其底层路由机制与可验证的运行行为。
为什么 FastAPI 可以轻松集成 GraphQL:ASGI 是前提
FastAPI 的底层基于 ASGI(Asynchronous Server Gateway Interface,异步服务器网关接口)标准。这一事实决定了任何同样兼容 ASGI 的 GraphQL 库都可以直接挂到 FastAPI 应用上,无需适配器或特殊改造。
更关键的一点是:普通的 FastAPI 路径操作(path operations)可以与 GraphQL 共存于同一个应用中。也就是说,你可以让 REST 风格的 API 端点和 GraphQL 端点共享同一个 FastAPI() 实例,各自承担不同职责。
选型提示(官方文档原话):GraphQL 只解决非常特定的应用场景。与常见的 Web API(如 REST)相比,它同时存在优势与劣势。在引入之前,请务必评估它为你的用例带来的收益是否足以抵消其带来的代价。
从源码结构看,这种"共存"能力来自 FastAPI 对标准 ASGI 应用的路由聚合机制。FastAPI 的 include_router() 方法定义于 fastapi/applications.py,其实现最终只是把参数透传给 self.router.include_router(...)(见该文件 L1633-L1644)。由于 Strawberry 的 GraphQLRouter 本身就是 APIRouter 的子类(即一个标准的 FastAPI/Starlette 路由容器),它才能被像普通 Router 一样挂载,并参与同一份 OpenAPI schema 的生成。
可选的 GraphQL 库及其 ASGI 集成方式
官方文档列出了以下具有 ASGI 支持、可与 FastAPI 配合使用的 GraphQL 库:
| 库 | 与 FastAPI 的集成方式 | 特点 |
|---|---|---|
| Strawberry 🍓 | 内置 FastAPI 集成文档,使用 strawberry.fastapi.GraphQLRouter |
全基于类型注解,设计上最接近 FastAPI |
| Ariadne | 提供专门的 FastAPI 集成文档 | 成熟的独立 GraphQL 框架 |
| Tartiflette | 通过独立的 Tartiflette ASGI 包提供 ASGI 集成 | 以 ASGI 中间件/应用形式接入 |
| Graphene | 通过 starlette-graphene3 包接入 | 与旧版 Starlette GraphQLApp 接口几乎一致,适合迁移 |
各库的完整用法请查阅其官方文档(仓库文档中已给出对应入口)。
推荐方案:Strawberry + FastAPI 完整集成
在需要或希望使用 GraphQL 的场景下,FastAPI 官方文档推荐 Strawberry,原因是:它的设计与 FastAPI 的设计最为接近——一切都基于类型注解(type annotations),而不是自定义的类体系与类型系统。文档同时保留了灵活性:如果你的用例更适合其他库,可以自由选择;但官方立场是"建议你优先尝试 Strawberry"。
FastAPI 仓库自带了一份可运行的集成示例,位于 docs_src/graphql_/tutorial001_py310.py。完整代码如下:
import strawberry
from fastapi import FastAPI
from strawberry.fastapi import GraphQLRouter
@strawberry.type
class User:
name: str
age: int
@strawberry.type
class Query:
@strawberry.field
def user(self) -> User:
return User(name="Patrick", age=100)
schema = strawberry.Schema(query=Query)
graphql_app = GraphQLRouter(schema)
app = FastAPI()
app.include_router(graphql_app, prefix="/graphql")
逐段解析(原文档用 hl[3,22,25] 标注了第 3、22、25 行为关键行):
- 定义类型与查询(L6-L16):
@strawberry.type把普通 Python 类标记为 GraphQL 对象类型(User),Query类上的@strawberry.field声明查询字段。这与 FastAPI 使用 Pydantic 模型 + 类型注解声明请求/响应的方式在风格上高度一致——这也是官方推荐它的核心原因。 - 构建 Schema(L19):
strawberry.Schema(query=Query)将所有查询类型组装成 GraphQL Schema。 - 创建 ASGI 路由(L22,关键行):
GraphQLRouter(schema)返回一个可直接挂载的路由容器,它内部实现了 GraphQL 端点的 GET(GraphiQL IDE)与 POST(执行查询)处理。 - 挂载到 FastAPI(L25,关键行):
app.include_router(graphql_app, prefix="/graphql")将其注册到/graphql前缀下。如前文所述,这一步走的就是 fastapi/applications.py 中的标准include_router()流程,因此 GraphQL 端点会和其他路径操作一样出现在应用的 OpenAPI 文档中。
依赖说明:该示例运行需要安装 Strawberry(strawberry-graphql 包)。FastAPI 仓库自身的测试依赖中已锁定该版本范围,见 pyproject.toml 的 tests 依赖组(strawberry-graphql >=0.200.0,<1.0.0,位于文件 L174)。当前仓库的 FastAPI 版本为 0.141.1(见 fastapi/init.py)。
运行时行为验证:查询响应与 OpenAPI 输出
仓库中配套的功能测试 tests/test_tutorial/test_graphql/test_tutorial001.py 直接导入了上面的示例应用(from docs_src.graphql_.tutorial001_py310 import app),并用 Starlette 的 TestClient 验证了两点,可作为集成成功与否的可验证依据:
1. POST 查询能正常返回 GraphQL 数据:
def test_query(client: TestClient):
response = client.post("/graphql", json={"query": "{ user { name, age } }"})
assert response.status_code == 200
assert response.json() == {"data": {"user": {"name": "Patrick", "age": 100}}}
2. GraphQL 端点自动进入 OpenAPI schema:/openapi.json 的快照断言显示,/graphql 路径包含 GET 与 POST 两个操作。其中 GET 操作的响应描述明确写着:
"The GraphiQL integrated development environment."
即 GET /graphql 在浏览器中打开时返回 GraphiQL 集成开发环境页面;若未启用,则返回 404。POST /graphql 用于执行 GraphQL 查询并返回 application/json 响应。
这两个断言意味着:只要照抄示例代码,你就获得了「浏览器里可交互的 GraphiQL 调试界面 + 标准 JSON 查询接口 + 与 FastAPI 文档统一展示」三合一的结果,无需任何额外配置。
旧版 Starlette GraphQLApp 的迁移方案
早期版本的 Starlette 曾内置一个 GraphQLApp 类,用于与 Graphene 集成。该类已从 Starlette 中废弃(deprecated)。如果你的存量代码仍在使用它,迁移路径非常直接:
- 迁移到 starlette-graphene3 包——它覆盖相同的使用场景,并且接口与旧
GraphQLApp几乎完全一致(almost identical interface),基本可以"换包名 + 换导入"完成迁移。
同时,官方文档在此再次给出提示:即便你只是为迁移而来,也值得评估 Strawberry——它基于类型注解而非自定义类与类型,与 FastAPI 的开发体验更一致。
总结与延伸阅读
- 前提:FastAPI 基于 ASGI,任何 ASGI 兼容的 GraphQL 库均可挂载,且能与普通路径操作共存于同一应用(路由聚合机制见 fastapi/applications.py)。
- 选型:Strawberry、Ariadne、Tartiflette、Graphene(经 starlette-graphene3)四条路线均可行;官方推荐 Strawberry,示例代码见 docs_src/graphql_/tutorial001_py310.py,验证用例见 tests/test_tutorial/test_graphql/test_tutorial001.py。
- 遗留代码:Starlette 旧版
GraphQLApp已废弃,迁移到 starlette-graphene3 即可平滑过渡。 - 决策:GraphQL 解决的是特定场景问题,引入前必须权衡其相对于常规 Web API 的利弊。
关于 GraphQL 规范本身,可查阅 GraphQL 官方文档;关于各库的完整 API 与进阶用法(认证、订阅、持久化查询等),请分别参阅 Strawberry、Ariadne、Tartiflette、Graphene 各项目的官方文档——FastAPI 仓库的这篇 how-to 聚焦的是"如何把它们接进来",而非 GraphQL 语言本身的完整教程。
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