用 FastAPI 与 Strawberry 构建 GraphQL 服务

FastAPI + Strawberry GraphQL 实战:类型注解定义 Schema、查询实现、Mutation 数据修改,打造类型安全、支持显式 Schema 演进的现代 API。

最佳实践
并发任务的多路径协同插画

直接回答:FastAPI 与 Strawberry GraphQL 是天作之合:两者都以 Python 类型注解为核心,Schema 定义就像写 dataclass 一样自然;组合起来得到高性能、类型安全、自动文档的 GraphQL 服务,兼容性仍需通过字段弃用策略和契约测试维护。

为什么这对组合

Strawberry 把 GraphQL Schema 写成带类型注解的 Python 类——与 FastAPI/Pydantic 的心智模型完全一致,需学习 GraphQL 类型、解析器和权限模型;FastAPI 提供 ASGI 高性能底座与依赖注入。两者相加,是 Python ASGI GraphQL 的一种组合。

搭建服务

pip install "fastapi[standard]" "strawberry-graphql[fastapi]"
# main.py
import strawberry
from fastapi import FastAPI
from strawberry.fastapi import GraphQLRouter

@strawberry.type
class Book:
    id: int
    title: str
    price: float

BOOKS = [Book(id=1, title="深入理解 Python", price=99.0)]

@strawberry.type
class Query:
    @strawberry.field
    def books(self) -> list[Book]:
        return BOOKS

schema = strawberry.Schema(query=Query)
app = FastAPI()
app.include_router(GraphQLRouter(schema), prefix="/graphql")

uvicorn main:app 启动,访问 /graphql 自带 GraphiQL IDE,立即查询:

query { books { title price } }

Schema 设计的要点

类型即文档:每个 @strawberry.type 自动进入 Schema,字段类型注解就是 GraphQL 类型。可选字段用 str | None,列表用 list[X]——Python 类型系统的表达力直接映射到 GraphQL。

Resolver 里的数据获取:

@strawberry.type
class Query:
    @strawberry.field
    async def book(self, id: int) -> Book | None:
        # 项目实现:按所用驱动的参数占位语法执行参数化查询
        row = await repository.get_book(id)
        return Book(**row) if row else None

Strawberry 的同步 resolver 也运行在事件循环中,不像 FastAPI 同步路由自动进入线程池;同步阻塞 IO 需显式卸载,异步 IO 应 await。

Mutation:数据修改

@strawberry.type
class Mutation:
    @strawberry.mutation
    def create_book(self, title: str, price: float) -> Book:
        book = Book(id=len(BOOKS) + 1, title=title, price=price)
        BOOKS.append(book)
        return book

schema = strawberry.Schema(query=Query, mutation=Mutation)
mutation { createBook(title: "GraphQL 实战", price: 79.0) { id } }

Mutation 示例仅用于本地内存演示,需把最终 schema 定义移到 GraphQLRouter 构造之前,已创建的 router 不会跟随变量重新赋值。生产应改为带认证、对象级权限和输入校验的事务写入;BOOKS 不持久化且不支持多进程一致性。复杂输入用 @strawberry.input。

生产清单

  • N+1 防护:嵌套 resolver 配 Strawberry 的 DataLoader 集成批量加载;
  • 深度/复杂度限制:strawberry 的查询分析扩展挡住恶意嵌套;
  • 鉴权:FastAPI 依赖注入进 GraphQL 上下文(context_getter),resolver 里读当前用户;
  • 订阅(Subscription):Strawberry 支持 WebSocket 订阅,实时场景直接可用。

常见问题(FAQ)

Q:Strawberry 和 Graphene 怎么选?
A:Strawberry 类型注解风格现代、异步友好,与 FastAPI 同气质;Graphene 老成,Django 集成深。FastAPI 项目可优先评估 Strawberry 的官方集成。

Q:GraphQL 适合所有 API 吗?
A:不。对外公开给不熟悉合作方的简单 API、文件上传下载、Webhook——REST 更直白。GraphQL 的甜区是"前端需求多变、数据关系复杂、多端消费"。

Q:怎么做接口版本管理?
A:GraphQL 哲学是"演进而非版本":字段只加不删,废弃用 @deprecated 标记。这正是它相对 REST v1/v2 的核心优势。

官方参考

本文基于官方文档整理,未进行运行时或性能测试。示例中的业务函数、数据模型和部署地址需结合项目补全;局部片段不等同于完整生产应用。

延伸阅读

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台