AX 爱鲜报

FastAPI 最佳实践

一份来自创业公司生产实践总结的 FastAPI 最佳实践与约定清单,涵盖项目结构、异步路由、Pydantic 用法、依赖注入、数据库与测试等主题,帮助开发者避开常见陷阱。

爱鲜报评分

0.0

0 人评分

18k

星数

是

中文

—

主语言

是

活跃

20

贡献者

人工分析

EDITORIAL

推荐理由

这是 FastAPI 社区最受欢迎的经验总结之一,1.8 万 Star 说明其内容经受住了大量开发者的检验。它不只讲 API 用法,而是从真实生产系统的踩坑经验出发,给出可落地的目录结构与编码约定。对于正在用 FastAPI 构建中大型项目、或想系统提升后端工程质量的开发者,非常值得通读。

适用场景

  • FastAPI 后端项目架构设计
  • 异步路由与阻塞 I/O 问题排查
  • Pydantic 模型与配置管理规范
  • 依赖注入与业务逻辑解耦
  • 团队编码规范与代码评审参考

优点

  • 内容源自真实创业公司生产系统,经验可信度高
  • 覆盖项目结构、异步、Pydantic、依赖、数据库、测试等完整链路
  • 配有大量正反例代码,直观展示错误写法与推荐写法
  • 提供机器可读的 AGENTS.md,方便与 AI 编码助手协作
  • 社区活跃、Star 数高,问题与讨论容易找到答案

缺点

  • 属于观点性约定(opinionated),并非官方标准,需结合团队情况取舍
  • 部分主题(如 Alembic、测试)仅给出方向,缺少完整可运行示例
  • 仓库以文档为主,不提供开箱即用的脚手架代码
  • 内容随 FastAPI 与 Pydantic 版本演进可能需自行核对时效性
上手难度 进阶

FastAPI 最佳实践

这是一份带有明确观点的 FastAPI 最佳实践与约定清单,来自作者在创业公司多年构建生产系统的经验总结。作者坦言,这些年既有正确的决策,也有带来痛苦教训的错误选择,本文正是把这些经验沉淀下来分享给社区。

仓库本身以文档为主,不是可运行的框架或脚手架,但内容密度很高,适合作为团队内部规范与代码评审的参考依据。

核心内容概览

  • 项目结构:推荐按业务域(domain)而非文件类型组织代码,每个模块自带 router.py、schemas.py、models.py、service.py、dependencies.py、constants.py、config.py、utils.py、exceptions.py 等文件,灵感来自 Netflix 的 Dispatch 项目。
  • 异步路由:区分 I/O 密集型与 CPU 密集型任务,强调不要在 async 路由中执行阻塞操作,否则会卡住整个事件循环。
  • Pydantic:鼓励“过度使用” Pydantic,自定义 Base Model,并将 BaseSettings 与业务代码解耦。
  • 依赖注入:介绍链式依赖、依赖缓存、依赖解耦与复用,以及优先使用 async 依赖。
  • 杂项约定:遵循 REST 风格、响应序列化、同步 SDK 放入线程池、BackgroundTasks 与真实任务队列的取舍、ValueError 与 Pydantic 校验错误的关系、文档、数据库命名约定、Alembic 迁移、SQL 优先、测试客户端从第一天就异步化、使用 ruff 等。

项目结构示例

作者推荐的结构大致如下(节选):

fastapi-project
├── alembic/
├── src
│   ├── auth
│   │   ├── router.py
│   │   ├── schemas.py
│   │   ├── models.py
│   │   ├── dependencies.py
│   │   ├── service.py
│   │   └── exceptions.py
│   ├── posts
│   ├── config.py
│   ├── database.py
│   └── main.py
├── tests/
├── requirements/
└── alembic.ini

跨模块引用时,建议使用显式模块名导入,例如 from src.auth import constants as auth_constants,避免命名冲突并提升可读性。

异步路由的关键区别

文档用三个路由对比说明问题:

@router.get("/terrible-ping")
async def terrible_ping():
    time.sleep(10)  # 阻塞事件循环,整个进程被卡住

@router.get("/good-ping")
def good_ping():
    time.sleep(10)  # 同步路由会被放入线程池,不阻塞事件循环

@router.get("/perfect-ping")
async def perfect_ping():
    await asyncio.sleep(10)  # 非阻塞 I/O,推荐写法

结论很清晰:async 路由中一旦出现阻塞调用,事件循环就无法处理其他请求;同步路由虽然会被 FastAPI 自动丢进线程池,但也不应滥用。

适合谁阅读

  • 正在用 FastAPI 搭建中大型后端服务的开发者
  • 需要为团队制定后端编码规范的 Tech Lead
  • 想深入理解异步、依赖注入与 Pydantic 实践细节的工程师

使用建议

本文属于观点性约定,不必全盘照搬。建议先通读一遍,再结合自己项目的规模、团队习惯与 FastAPI/Pydantic 版本,挑选适合的部分落地。仓库还提供了 AGENTS.md,以更简洁、机器可读的格式呈现同样的规则,方便与 AI 编码助手配合使用。

评论

登录后才可评论与评分

0 条评论

  • 暂无评论,来写第一条吧。