Django REST Framework 太重,Flask 太裸。FastAPI 在这两者之间找到了一个很好的平衡点。
为什么是 FastAPI
- 快:基于 Starlette,性能接近 Node.js
- 自动文档:自动生成 Swagger UI 和 ReDoc
- 类型驱动:用 Pydantic 做数据校验,写一次模型,校验和文档都有了
- 原生异步:完整支持 async/await
5 分钟上手
uv pip install fastapi uvicorn
# main.py
from fastapi import FastAPI
app = FastAPI(title="我的 API", version="1.0.0")
@app.get("/")
def read_root():
return {"message": "Hello, World!"}
@app.get("/users/{user_id}")
def get_user(user_id: int, include_orders: bool = False):
return {"user_id": user_id, "include_orders": include_orders}
uvicorn main:app --reload
# 访问 http://localhost:8000/docs 看自动生成的文档
Pydantic 模型:请求/响应的核心
from pydantic import BaseModel, EmailStr, Field
from datetime import datetime
class UserCreate(BaseModel):
name: str = Field(..., min_length=2, max_length=50)
email: EmailStr
age: int = Field(..., ge=0, le=150)
class UserResponse(BaseModel):
id: int
name: str
email: str
created_at: datetime
class Config:
from_attributes = True # 支持从 ORM 对象创建
@app.post("/users", response_model=UserResponse, status_code=201)
def create_user(user: UserCreate):
# FastAPI 自动解析请求体、校验字段、返回时过滤多余字段
db_user = save_to_db(user)
return db_user
Pydantic 的 Field 支持的校验相当丰富:字符串长度、数字范围、正则表达式……不需要手写校验逻辑。
依赖注入
FastAPI 的依赖注入系统是它最优雅的设计之一:
from fastapi import Depends, HTTPException
from sqlalchemy.orm import Session
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
def get_current_user(
token: str = Depends(oauth2_scheme),
db: Session = Depends(get_db)
) -> User:
user = verify_token(token, db)
if not user:
raise HTTPException(status_code=401, detail="Invalid token")
return user
@app.get("/me")
def read_profile(current_user: User = Depends(get_current_user)):
return current_user
数据库连接、认证、权限控制都可以用 Depends 组合,逻辑清晰且可复用。
异步路由
import httpx
@app.get("/external-data")
async def fetch_external():
async with httpx.AsyncClient() as client:
response = await client.get("https://api.example.com/data")
return response.json()
需要异步的路由加 async def,不需要的用普通 def,FastAPI 会自动在线程池里运行同步路由,不阻塞事件循环。
错误处理
from fastapi import HTTPException
from fastapi.responses import JSONResponse
from fastapi.requests import Request
# 自定义异常
class OrderNotFoundError(Exception):
def __init__(self, order_id: int):
self.order_id = order_id
@app.exception_handler(OrderNotFoundError)
async def order_not_found_handler(request: Request, exc: OrderNotFoundError):
return JSONResponse(
status_code=404,
content={"error": {"code": "ORDER_NOT_FOUND", "message": f"订单 {exc.order_id} 不存在"}}
)
和 Flask 的对比感受
从 Flask 迁过来之后,最大的感受是:不用写那么多样板代码了。参数解析、类型转换、校验报错、文档生成,以前需要自己写或者靠各种插件,FastAPI 都内置了。如果在新项目里选框架,我现在会毫不犹豫选 FastAPI。