FastAPI 集成 GraphQL 实战指南:基于 ASGI 的 Strawberry 深度整合
FastAPI 基于 ASGI 标准构建,因此可以轻松集成任何同样兼容 ASGI 的 GraphQL 库,在同一应用中同时提供常规 path operation 与 GraphQL 端点。本文以官方文档 docs/ja/docs/how-to/graphql.md 为核心,结合仓库中的源码示例与测试用例,讲解如何在 FastAPI 中落地 GraphQL:如何选型、如何用推荐的 Strawberry 完成从 Schema 定义到路由挂载的完整流程,以及如何从 Starlette 旧版 GraphQLApp 平滑迁移。读完本文,你将能在自己的 FastAPI 应用中独立搭建一套可运行、可测试的 GraphQL 服务。
提示:GraphQL 解决的是非常特定的使用场景。与常见的 Web API 相比,它有优势也有劣势。请务必评估在自身场景中获得的收益是否足以弥补代价。🤓
为什么 FastAPI 集成 GraphQL 如此简单:ASGI 标准是基石
FastAPI 之所以能与 GraphQL 无缝对接,根源在于它建立在 ASGI(Asynchronous Server Gateway Interface)标准之上。从源码看,fastapi/applications.py 直接导入了 Starlette 的 ASGIApp 类型(from starlette.types import ASGIApp, ...),FastAPI 类内部通过 self.middleware_stack: ASGIApp | None 维护整个应用的可组合中间件栈,并调用 build_middleware_stack() 构建。
这意味着 FastAPI 应用本质上就是一个符合 ASGI 协议的 Python 应用对象。任何同样实现了 ASGI 接口的 GraphQL 服务,都可以作为子应用被挂载进 FastAPI,两者在协议层天然互通。因此,只要某个 GraphQL 库支持 ASGI,就能与 FastAPI 协作——无需胶水代码,也无需适配层。
支持 ASGI 的 GraphQL 库选型
以下是文档列出的、具备 ASGI 支持、可与 FastAPI 配合使用的 GraphQL 库:
- Strawberry 🍓
- 提供面向 FastAPI 的专门集成文档
- Ariadne
- 提供面向 FastAPI 的集成文档
- Tartiflette
- 通过 Tartiflette ASGI 提供 ASGI 集成能力
- Graphene
- 通过 starlette-graphene3 提供 ASGI 集成能力
其中,官方文档对 Strawberry 给出了明确推荐:如果你需要(或想要)使用 GraphQL,Strawberry 是推荐选择,因为它的设计与 FastAPI 的设计最为接近——一切都建立在**类型注解(type annotations)**之上。这与 FastAPI 以 Python 类型系统驱动校验、序列化与文档生成的核心理念一脉相承。当然,具体选型仍取决于你的使用场景,但 Strawberry 通常是最值得先尝试的方案。
Strawberry 实战:从 Schema 到路由的完整集成
完整示例代码
仓库中提供了可直接运行的集成示例 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")
官方文档中该示例高亮了第 3、22、25 三行,恰好对应集成的三个关键步骤:
第一步:导入 GraphQLRouter
from strawberry.fastapi import GraphQLRouter
Strawberry 在 strawberry.fastapi 子模块中提供了针对 FastAPI 的 GraphQLRouter 类。它是 ASGI 集成层的核心,负责把 GraphQL 请求处理逻辑封装成一个 FastAPI 可直接挂载的 APIRouter。
第二步:用类型注解定义 Schema 并创建实例
@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)
这里完整展示了 Strawberry 的"类型注解驱动"风格:
- 用
@strawberry.type装饰器把普通 Python 类User变成 GraphQL 对象类型,字段name、age直接由类型注解推断; - 定义根查询类型
Query,其中的user字段通过@strawberry.field标记为可查询字段,返回类型User即 GraphQL 返回的对象类型; - 最后用
strawberry.Schema(query=Query)汇总生成 GraphQL Schema。
这种写法与 FastAPI 用类型注解声明路径参数、请求体、响应模型的方式高度一致,学习成本极低。
第三步:实例化 Router 并挂载到 FastAPI 应用
graphql_app = GraphQLRouter(schema)
app = FastAPI()
app.include_router(graphql_app, prefix="/graphql")
GraphQLRouter(schema) 接收 Schema 生成路由对象,然后通过 app.include_router(...) 挂载到 FastAPI 应用上,并指定 prefix="/graphql",使 GraphQL 端点位于 /graphql。
include_router 是 fastapi/applications.py 中 FastAPI 类的标准方法,其签名支持 prefix(可选路径前缀)、tags(应用于该路由下所有 path operation 的标签,会反映到生成的 OpenAPI 文档中)、dependencies(应用于所有 path operation 的依赖列表)等参数。因此你可以在挂载 GraphQL 路由时顺带配置标签与依赖,与挂载普通 APIRouter 的体验完全一致——GraphQL 端点对 FastAPI 而言就是一组普通路由。
测试验证:查询与 OpenAPI 文档
仓库为上述示例编写了完整的测试 tests/test_tutorial/test_graphql/test_tutorial001.py,可以作为集成正确性的直接验证:
GraphQL 查询测试:向 /graphql 发送 POST 请求,携带查询 { user { name, age } },断言返回 200 且响应体为 {"data": {"user": {"name": "Patrick", "age": 100}}}:
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}}}
OpenAPI 文档测试:/openapi.json 中会自动出现 /graphql 路径,且包含两个操作:
GET /graphql:响应描述为 "The GraphiQL integrated development environment."(GraphiQL 交互式开发环境),另有 404 描述 "Not found if GraphiQL or query via GET are not enabled."(若未启用 GraphiQL 或 GET 查询则返回 404);POST /graphql:响应描述为 "Successful Response"(成功响应)。
这印证了 Strawberry 的 GraphQLRouter 默认行为:既提供基于 POST 的查询入口,也提供基于 GET 的 GraphiQL 可视化调试界面,且这些路由会自动进入 FastAPI 的 OpenAPI 文档体系(/docs、/redoc 可见)。这也再次说明 GraphQL 集成与 FastAPI 现有路由机制、文档生成机制完全兼容,你可以把普通 REST 接口与 GraphQL 端点放在同一个应用中混合使用。
运行方式
示例应用即为一个标准的 FastAPI 应用。克隆仓库后,在虚拟环境中安装依赖(项目使用 uv 管理,见 uv.lock)并安装 strawberry-graphql,即可运行:
uv run uvicorn docs_src.graphql_.tutorial001_py310:app --reload
随后访问 http://127.0.0.1:8000/graphql 打开 GraphiQL 界面,或直接向 /graphql 发送 POST 查询请求;同时可访问 http://127.0.0.1:8000/docs 查看自动生成的 API 文档。
迁移指南:从 Starlette 旧版 GraphQLApp 到 starlette-graphene3
早期版本的 Starlette 内置了用于集成 Graphene 的 GraphQLApp 类。该功能后来已从 Starlette 中弃用。如果你仍在使用 GraphQLApp 的旧代码,可以轻松迁移到 starlette-graphene3——它覆盖了同样的使用场景,且提供了几乎完全一致的接口,迁移成本很低,只需调整导入来源即可。
需要说明的是,如果从零开始且确实需要 GraphQL,官方文档依然推荐优先考察 Strawberry,理由是它基于类型注解而非自定义类和类型体系,与 FastAPI 的哲学更加契合。
进一步学习
- GraphQL 语言本身:可以深入学习 GraphQL 的官方文档,理解查询、变更、订阅、Schema 定义等核心概念;
- Strawberry:查阅 Strawberry 的官方文档,重点阅读其 FastAPI 集成章节,了解
GraphQLRouter的更多选项(如 context、权限、订阅支持等); - 其他库:本文提到的 Ariadne、Tartiflette(配合 Tartiflette ASGI)、Graphene(配合 starlette-graphene3)各有其适用场景,可按需查阅各自文档。
文档结构上,该主题位于英文文档的 how-to 章节(见 docs/en/mkdocs.yml),并同步维护于日文等多个语言版本(如 docs/ja/docs/how-to/graphql.md),属于官方推荐的实践指南之一。
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 StartedRust0629
MiniCPM5-2BMiniCPM5-2B 是一款面向端侧、本地部署和资源受限场景的 2B 稠密 Transformer,能够达到同尺寸开源模型 SOTA 水平。Markdown00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
HivisionIDPhotos⚡️HivisionIDPhotos: a lightweight and efficient AI ID photos tools. 一个轻量级的AI证件照制作算法。Python07
DragonOSDragonOS is an operating system developed from scratch using Rust, with Linux compatibility. It is designed for **Serverless** scenarios. 使用Rust从0自研内核,具有Linux兼容性的操作系统,面向云计算Serverless场景而设计。Rust00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00