FastAPI入门:从Python后端“菜鸟”到能扛项目的实战手记
引言:为什么是FastAPI?

作为一个刚入行不久的全栈开发工程师,我第一次接触后端开发的时候用的是Django。那会儿我觉得Django很强大、功能齐全,但总觉得它有点“重”,特别是当你想快速搭建一个接口服务、追求性能和速度时,Django并不是最轻量的选择。
后来因为公司项目需要快速迭代,我们团队决定尝试用更现代的框架来构建后端服务。在对比了Flask和FastAPI之后,我们最终选择了FastAPI。刚开始接触的时候,我也是一头雾水,文档看着挺简单,但真正上手写项目才发现有很多需要注意的地方。今天我就想通过我的实际经历,带大家一步一步走进FastAPI的世界。
项目背景:我们要做什么?

事情起源于我们为一家小型电商客户做的后台系统迁移项目。原来的系统是基于Node.js写的,但由于前端改用Vue3重构,而我们团队内部又都是Python背景,所以决定用Python来重构整个后端系统。
核心需求:
- 提供商品管理、订单管理、用户管理等基础接口
- 支持高并发访问(至少1000 QPS)
- 接口需要支持Swagger文档化
- 对接MySQL数据库
- 代码结构清晰,方便后续维护和扩展
在调研框架的过程中,我们考虑过Flask、Tornado,甚至还有Django REST Framework。但最后被FastAPI的亮点打动了:
- 自动生成交互式API文档(Swagger & ReDoc)
- 基于Python类型提示,自动参数校验
- 异步支持
- 高性能,接近Node.js级别的吞吐能力
于是我们决定采用FastAPI作为主框架开始搭建。
挑战来了:第一次实战遇到的问题

虽然FastAPI官方文档很友好,看起来也很简洁易懂,但真正动手写第一个接口的时候,我还是踩了不少坑。下面我来详细讲几个我当时遇到的真实问题。
问题一:依赖安装与版本混乱
我们在本地使用pip安装fastapi和uvicorn,但不同的环境中有时候出现版本不一致的情况,导致某些功能无法运行。比如:
pip install fastapi uvicorn sqlalchemy pydantic
一开始我没注意版本兼容性,结果上线前测试发现pydantic报错,查了一圈发现是fastapi依赖的pydantic版本不对。建议:
✅ 统一使用requirements.txt或Poetry进行依赖管理,并在不同环境保持版本一致。
问题二:数据库连接设计不合理
我最初把数据库连接写在每个路由函数中,造成大量的冗余代码。后来发现这样非常不利于维护和扩展。后来改成使用中间件注入DB Session的方式,大大提升了可维护性。
问题三:异步处理写法不熟
由于FastAPI支持异步请求处理,我在初期没有意识到同步与异步调用的区别,比如用了普通的requests.get()却没加await,直接导致接口阻塞。这个问题花了我大半天时间才定位。
解决方案:如何正确使用FastAPI?

既然问题已经暴露出来了,那就一一解决。以下是我总结出的一些关键点和实践方式。
1. 项目结构设计(推荐)
我把整个项目的结构按照模块划分,大致如下:
.
├── app/
│ ├── main.py
│ ├── routers/
│ │ ├── products.py
│ │ ├── orders.py
│ │ └── users.py
│ ├── models/ # 数据模型
│ ├── schemas/ # Pydantic Schema
│ ├── database.py # 数据库连接配置
│ └── utils/ # 工具类
└── requirements.txt
这种结构非常适合中型项目,易于维护和扩展。
2. 数据库层设计:SQLAlchemy + Async
我们用的是SQLAlchemy作为ORM,并结合asyncpg实现了异步操作。关键在于database.py文件中的设置:
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
DATABASE_URL = "postgresql+asyncpg://user:password@localhost/dbname"
engine = create_async_engine(DATABASE_URL, echo=True)
AsyncSessionLocal = sessionmaker(
bind=engine, class_=AsyncSession, expire_on_commit=False
)
Base = declarative_base()
async def get_db():
async with AsyncSessionLocal() as session:
yield session
然后在路由中通过依赖注入获取DB连接:
from fastapi import Depends
from sqlalchemy.ext.asyncio import AsyncSession
@app.get("/products/{product_id}")
async def read_product(product_id: int, db: AsyncSession = Depends(get_db)):
result = await db.execute(...)
...
这样就能优雅地进行异步数据库操作。
3. 接口设计遵循RESTful规范
FastAPI天然支持RESTful风格,我们在定义资源路径时严格按照CRUD操作设计:
| HTTP方法 | 路径示例 | 说明 |
|---|---|---|
| GET | /products | 获取所有商品列表 |
| GET | /products/{id} | 获取某一个商品详情 |
| POST | /products | 创建一个新的商品 |
| PUT | /products/{id} | 更新指定ID的商品信息 |
| DELETE | /products/{id} | 删除指定ID的商品 |

同时使用Pydantic来定义输入输出的数据格式:
from pydantic import BaseModel
class ProductCreate(BaseModel):
name: str
price: float
class ProductResponse(ProductCreate):
id: int
再结合路由定义时自动完成校验:
@app.post("/products", response_model=ProductResponse)
async def create_product(product: ProductCreate, db: AsyncSession = Depends(get_db)):
...
这样不仅增强了接口的安全性和健壮性,还能自动生成交互式文档。
实战代码片段分享
路由定义
我们以创建商品为例:
from fastapi import APIRouter, Depends
from sqlalchemy.ext.asyncio import AsyncSession
from app.models.product import Product
from app.schemas import ProductCreate, ProductResponse
from app.utils.crud import create_new_product
router = APIRouter()
@router.post("/", response_model=ProductResponse)
async def create_product(
product: ProductCreate,
db: AsyncSession = Depends(get_db)
):
return await create_new_product(db, product)
CRUD操作(异步版)
from sqlalchemy.future import select
from app.models import Product
async def create_new_product(db: AsyncSession, product: ProductCreate):
new_product = Product(**product.dict())
db.add(new_product)
await db.commit()
await db.refresh(new_product)
return new_product
是不是很清晰?这就是FastAPI+Pydantic+SQLAlchemy的组合拳,简洁又高效。
实战经验与踩坑记录
这部分我想分享一些在真实项目中踩过的坑,希望能帮你们避雷。
坑一:异步调用不彻底
我之前为了提升性能,将很多IO操作改成了异步,但在某个外部API调用中还用了同步的requests,结果整个接口都卡住了,因为requests不支持await。
🔧解决办法:换成httpx库,支持异步请求:
import httpx
async def external_api_call():
async with httpx.AsyncClient() as client:
resp = await client.get("https://example.com/api")
return resp.json()
坑二:生成文档时字段别名显示异常
有些时候我们需要返回字段名不是Python命名风格(例如驼峰),而是前端更习惯的camelCase,比如:
class UserSchema(BaseModel):
user_name: str
birthDate: date
class Config:
fields = {
"birthDate": {"alias": "birthDate"}
}
如果你不显式声明fields映射,FastAPI生成的文档中还是会出现user_name而不是前端期望的userName。这个一定要注意!
坑三:部署生产环境时的注意事项
我们在部署到线上服务器时使用了Gunicorn+Nginx+Uvicorn的组合:
gunicorn -k uvicorn.workers.UvicornWorker --bind :8000 app.main:app
但是要注意,如果是多核机器,可以开启多个worker提高并发能力:
gunicorn -w 4 -k uvicorn.workers.UvicornWorker --bind :8000 app.main:app
另外,还要注意配置超时时间和日志级别,避免因长时间阻塞导致连接断开。
效果总结:FastAPI带来的变化
项目上线后,我们做了几次压力测试。使用Locust对关键接口进行压测:
| 接口 | 平均响应时间 | 最大QPS |
|---|---|---|
| 商品列表GET | 50ms | 1300 |
| 下单POST | 80ms | 900 |
相比之前的Node.js版本(平均QPS 900左右),性能基本持平,甚至还略优。而且由于我们团队熟悉Python生态,整体开发效率提升了不少,后期运维也更容易。
另外,Swagger文档的自动化生成功能让我们省去了大量写接口文档的时间。产品经理可以直接看文档进行联调,沟通成本大幅下降。
经验总结与建议
FastAPI真的是个非常好用的工具,尤其是对于Python开发者来说,学习曲线平缓,社区活跃,文档完善。
但要真正发挥它的威力,还是有几个点要特别注意:
✅ 合理使用异步特性
不要盲目加async/await,只有涉及IO操作时才有必要。否则反而会影响性能。
✅ 设计好数据模型(Schema)与ORM映射
提前规划好数据库表结构,使用Pydantic做统一校验,减少后端逻辑中的判断语句。
✅ 规范接口文档,提前与前端约定好字段格式
这能让你少写很多debug时间,也能让产品理解你做了什么。
✅ 不要小看性能优化细节
即使FastAPI本身很快,但如果数据库查询没有做好索引优化,接口也会慢下来。记得经常分析慢查询日志。
写在最后:我的成长感悟
说实话,刚开始用FastAPI写项目的时候我是有点慌的,毕竟不像Django那样成熟稳定。但随着项目推进,我发现它带给我的便利远远超出想象。
FastAPI不仅仅是一个框架,更是一种现代化Web开发思维的体现:类型即约束、文档即代码、接口即服务。它教会了我如何写出更清晰、更高效的后端代码。
如果你是刚刚开始接触后端开发的朋友,或者已经有一定的Python基础但想找一个更现代的框架练手,我真心推荐你试试FastAPI——它真的会让你爱上写接口这件事。
📌 附录推荐学习资源
希望这篇结合实战经验的文章对你有所帮助。如果你也在用FastAPI开发项目,欢迎留言交流,我们一起成长!💻🚀

评论 0