大家好,我是Java1234_小锋老师。
写 FastAPI 项目久了,你会发现:框架本身不难,难的是把代码写得干净、好维护、上线不出幺蛾子。下面这 10 个技巧,都是日常开发里真用得上的,每条都配了可以直接跑的 demo。

1. 用 Pydantic 模型做请求校验,少写一半 if 判断
以前写接口,总要手动判断「用户名不能为空」「年龄必须是数字」…… FastAPI 配合 Pydantic,这些活它帮你干了。
from fastapi import FastAPI
from pydantic import BaseModel, Field
app = FastAPI()
class UserCreate(BaseModel):
username: str = Field(..., min_length=3, max_length=20, description="用户名")
age: int = Field(..., ge=1, le=120, description="年龄")
email: str | None = None
@app.post("/users")
def create_user(user: UserCreate):
# 走到这里,数据已经是合法的了
return {"msg": f"用户 {user.username} 创建成功", "data": user}
请求体不合法时,FastAPI 会自动返回 422 和详细错误信息,Swagger 文档里也能看到字段说明。省下来的时间,够你多摸一会儿鱼。
2. 依赖注入:把数据库连接、登录校验抽出来复用
同一个「获取当前登录用户」的逻辑,如果在每个接口里 copy 一遍,迟早要出 bug。用 Depends 抽成依赖,写一次、到处用。
from fastapi import Depends, FastAPI, HTTPException, Header
app = FastAPI()
# 模拟用户表
fake_users = {"token-abc": {"id": 1, "name": "张三"}}
def get_current_user(authorization: str = Header(...)):
token = authorization.replace("Bearer ", "")
user = fake_users.get(token)
if not user:
raise HTTPException(status_code=401, detail="请先登录")
return user
@app.get("/profile")
def get_profile(user: dict = Depends(get_current_user)):
return {"user": user}
@app.get("/orders")
def get_orders(user: dict = Depends(get_current_user)):
return {"user_id": user["id"], "orders": ["订单A", "订单B"]}
测试也友好——测试时可以替换依赖,不用真的走登录流程。
3. 路由分组 + APIRouter,项目大了也不乱
项目接口一多,全堆在 main.py 里就没法看了。按业务模块拆路由,结构清晰很多。
# main.py
from fastapi import FastAPI
from routers import user, product
app = FastAPI(title="商城 API")
app.include_router(user.router, prefix="/api/users", tags=["用户"])
app.include_router(product.router, prefix="/api/products", tags=["商品"])
# routers/user.py
from fastapi import APIRouter
router = APIRouter()
@router.get("/")
def list_users():
return [{"id": 1, "name": "张三"}]
@router.get("/{user_id}")
def get_user(user_id: int):
return {"id": user_id, "name": "张三"}
打开 /docs,接口按 tag 分组展示,前端同事找接口也方便。
4. lifespan 管理启动和关闭,资源别泄漏
连接池、Redis、消息队列这些资源,要在应用启动时初始化、关闭时释放。FastAPI 推荐用 lifespan,比老的 @app.on_event 更规范。
from contextlib import asynccontextmanager
from fastapi import FastAPI
db_pool = None # 假装是数据库连接池
@asynccontextmanager
async def lifespan(app: FastAPI):
global db_pool
print("🚀 应用启动,初始化连接池...")
db_pool = {"connected": True}
yield
print("👋 应用关闭,释放连接池...")
db_pool = None
app = FastAPI(lifespan=lifespan)
@app.get("/health")
def health():
return {"db": "ok" if db_pool else "down"}
本地开发可能感觉不明显,上了生产环境,这个习惯能帮你少踩不少坑。
5. 统一异常处理,前端收到的错误格式一致
不同接口返回不同格式的错误,前端要写一堆兼容逻辑。注册全局异常处理器,统一包装成 {code, message} 就行。
from fastapi import FastAPI, Request
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
app = FastAPI()
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
return JSONResponse(
status_code=422,
content={"code": 422, "message": "参数校验失败", "detail": exc.errors()},
)
@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
return JSONResponse(
status_code=500,
content={"code": 500, "message": "服务器内部错误"},
)
前端同学会感谢你的。
6. BackgroundTasks 做轻量异步,不必什么都上 Celery
发邮件、写日志、更新统计——这类「不用等结果」的操作,用 BackgroundTasks 就够了,不必为了几行代码引入 Celery + Redis。
from fastapi import BackgroundTasks, FastAPI
app = FastAPI()
def send_welcome_email(email: str):
print(f"📧 正在给 {email} 发送欢迎邮件...")
@app.post("/register")
def register(email: str, background_tasks: BackgroundTasks):
background_tasks.add_task(send_welcome_email, email)
return {"msg": "注册成功,邮件稍后送达"}
接口立刻返回,邮件在后台慢慢发。任务量大、需要重试和调度时,再考虑 Celery 也不迟。
7. response_model 控制返回字段,别把密码带出去
数据库查出来的用户对象,可能带着 password_hash。用 response_model 指定返回结构,敏感字段自动过滤。
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class UserInDB(BaseModel):
id: int
username: str
password_hash: str # 数据库里有,但不能返回
class UserOut(BaseModel):
id: int
username: str
fake_db = UserInDB(id=1, username="张三", password_hash="e10adc3949ba59abbe56e057f20f883e")
@app.get("/users/me", response_model=UserOut)
def get_me():
return fake_db # 只返回 UserOut 里定义的字段
多一层保险,比手动 del user.password 靠谱。
8. Query / Path / Body 参数写清楚,文档自动生成
FastAPI 的 Swagger 文档是自动生成的,但前提是参数要写规范。加上 description、example,文档立刻好用很多。
from fastapi import FastAPI, Query, Path
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
@app.get("/items/{item_id}")
def get_item(
item_id: int = Path(..., ge=1, description="商品 ID", example=1),
keyword: str = Query(None, description="搜索关键词", example="手机"),
page: int = Query(1, ge=1, description="页码"),
size: int = Query(10, ge=1, le=100, description="每页条数"),
):
return {"item_id": item_id, "keyword": keyword, "page": page, "size": size}
@app.post("/items")
def create_item(item: Item):
return {"msg": "创建成功", "item": item}
启动后访问 /docs,参数说明、示例值一目了然,联调效率翻倍。
9. 中间件打日志、记耗时,排查问题快很多
线上出问题时,「这个请求到底花了多久」是第一要问的。写个简单中间件,每个请求自动记日志。
import time
from fastapi import FastAPI, Request
app = FastAPI()
@app.middleware("http")
async def log_requests(request: Request, call_next):
start = time.time()
response = await call_next(request)
duration = round((time.time() - start) * 1000, 2)
print(f"{request.method} {request.url.path} -> {response.status_code} ({duration}ms)")
response.headers["X-Process-Time"] = str(duration)
return response
@app.get("/slow")
async def slow_api():
import asyncio
await asyncio.sleep(0.5)
return {"msg": "慢接口演示"}
响应头里带上 X-Process-Time,用 Postman 或浏览器开发者工具都能直接看到。
10. 用 TestClient 写接口测试,改代码心里踏实
改了一个接口,不确定有没有把别的搞坏?FastAPI 自带 TestClient,不用起真实服务就能测。
# test_main.py
from fastapi.testclient import TestClient
from main import app # 假设 main.py 里有 app
client = TestClient(app)
def test_health():
response = client.get("/health")
assert response.status_code == 200
def test_create_user():
response = client.post("/users", json={
"username": "testuser",
"age": 25,
})
assert response.status_code == 200
assert "创建成功" in response.json()["msg"]
def test_create_user_invalid_age():
response = client.post("/users", json={
"username": "test",
"age": -1,
})
assert response.status_code == 422
配合 pytest 跑一下,CI 里挂个自动测试,重构时底气足很多。
最终小结下哈
FastAPI 上手快,但要写得「稳」,靠的往往是这些细节:校验、依赖注入、路由拆分、资源管理、统一错误、合理异步、安全返回、规范参数、可观测性、自动化测试。
不用一次全用上,挑几条先落地,项目质量就会有肉眼可见的提升。祝你写接口越来越顺!
运行 demo 的最小依赖:
pip install fastapi uvicorn pytest httpx
uvicorn main:app --reload
访问 http://127.0.0.1:8000/docs 即可查看自动生成的 API 文档。
43万+

被折叠的 条评论
为什么被折叠?



