1. 为什么选择FastAPI+SQLAlchemy组合
在Python后端开发领域,FastAPI和SQLAlchemy的组合已经成为现代Web应用开发的事实标准。这个技术栈的火爆程度从GitHub的star增长曲线就能看出——FastAPI在短短几年内就获得了超过5万star,而SQLAlchemy作为老牌ORM更是长期占据Python数据库工具榜首。
我最初接触这个组合是在2019年,当时正在为一个电商平台重构后端API。从Flask切换到FastAPI后,接口响应时间直接降低了40%,开发效率提升明显。特别是配合SQLAlchemy 2.0的异步支持,整个系统的并发处理能力上了一个台阶。
这个组合的核心优势在于:
- FastAPI提供了现代Python Web框架的所有特性:自动文档生成、数据验证、依赖注入等
- SQLAlchemy作为Python最强大的ORM,支持从简单CRUD到复杂查询的所有场景
- 两者都原生支持异步IO,适合高并发场景
- 完善的类型提示让代码更健壮,IDE支持更好
提示:如果你是从Flask或Django转过来的开发者,需要注意FastAPI的异步特性会带来一些思维转变,但适应后会发现这种模式更符合现代Web开发需求。
2. 环境准备与项目初始化
2.1 安装必备依赖
首先确保你的Python版本≥3.7(推荐3.8+),然后创建虚拟环境:
bash复制python -m venv venv
source venv/bin/activate # Linux/Mac
venv\Scripts\activate # Windows
安装核心依赖包:
bash复制pip install fastapi sqlalchemy uvicorn python-dotenv
这里有几个关键点需要注意:
uvicorn是ASGI服务器,用于运行FastAPI应用python-dotenv用于管理环境变量- SQLAlchemy 2.x版本已经稳定,推荐使用最新版
2.2 项目结构设计
一个良好的项目结构能大幅提升后期维护效率。我推荐如下结构:
code复制project/
├── app/
│ ├── __init__.py
│ ├── main.py # FastAPI应用入口
│ ├── models/ # SQLAlchemy模型
│ ├── schemas/ # Pydantic模型
│ ├── crud/ # 数据库操作
│ ├── database.py # 数据库配置
│ └── config.py # 配置管理
├── tests/ # 测试代码
├── .env # 环境变量
└── requirements.txt # 依赖列表
这种结构清晰分离了不同职责的代码,特别适合中大型项目。对于小型项目,可以适当简化。
3. 数据库配置与模型定义
3.1 配置SQLAlchemy连接
在database.py中配置数据库连接:
python复制from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
SQLALCHEMY_DATABASE_URL = "sqlite:///./sql_app.db"
# 生产环境推荐使用PostgreSQL:
# postgresql://user:password@postgresserver/db
engine = create_engine(
SQLALCHEMY_DATABASE_URL,
connect_args={"check_same_thread": False} # SQLite专用
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
关键配置说明:
create_engine的参数echo=True可以在开发时打印SQL语句SessionLocal是数据库会话工厂,每个请求应该有自己的会话Base是所有模型类的基类
3.2 定义数据模型
在models/user.py中定义用户模型:
python复制from sqlalchemy import Column, Integer, String
from .database import Base
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
email = Column(String, unique=True, index=True)
hashed_password = Column(String)
full_name = Column(String, nullable=True)
# 定义与其它模型的关系
# items = relationship("Item", back_populates="owner")
模型定义的最佳实践:
- 总是显式定义
__tablename__ - 为常用查询字段添加
index=True - 使用
nullable明确字段是否允许为空 - 关系定义使用新的2.0样式(后面会详细介绍)
4. CRUD操作实现
4.1 创建记录
在crud/user.py中实现创建逻辑:
python复制from sqlalchemy.orm import Session
from .models import User
from .schemas import UserCreate
def create_user(db: Session, user: UserCreate):
fake_hashed_password = user.password + "notreallyhashed"
db_user = User(
email=user.email,
hashed_password=fake_hashed_password,
full_name=user.full_name
)
db.add(db_user)
db.commit()
db.refresh(db_user)
return db_user
关键点:
db.add()将对象添加到会话db.commit()提交事务db.refresh()从数据库重新加载最新状态
4.2 查询操作
实现各种查询方法:
python复制def get_user(db: Session, user_id: int):
return db.query(User).filter(User.id == user_id).first()
def get_user_by_email(db: Session, email: str):
return db.query(User).filter(User.email == email).first()
def get_users(db: Session, skip: int = 0, limit: int = 100):
return db.query(User).offset(skip).limit(limit).all()
查询技巧:
- 使用
filter()替代老的filter_by()(2.0风格) first()获取单个结果,all()获取所有结果offset()和limit()实现分页
5. FastAPI路由与依赖注入
5.1 创建路由
在main.py中定义API端点:
python复制from fastapi import FastAPI, Depends, HTTPException
from sqlalchemy.orm import Session
from . import crud, models, schemas
from .database import SessionLocal, engine
models.Base.metadata.create_all(bind=engine)
app = FastAPI()
# 依赖项
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.post("/users/", response_model=schemas.User)
def create_user(user: schemas.UserCreate, db: Session = Depends(get_db)):
db_user = crud.get_user_by_email(db, email=user.email)
if db_user:
raise HTTPException(status_code=400, detail="Email already registered")
return crud.create_user(db=db, user=user)
@app.get("/users/{user_id}", response_model=schemas.User)
def read_user(user_id: int, db: Session = Depends(get_db)):
db_user = crud.get_user(db, user_id=user_id)
if db_user is None:
raise HTTPException(status_code=404, detail="User not found")
return db_user
路由设计要点:
- 使用
Depends实现依赖注入 - 每个请求获取独立的数据库会话
- 通过
response_model实现输出数据验证和转换
5.2 异常处理
FastAPI提供了完善的异常处理机制:
python复制from fastapi import HTTPException, status
@app.get("/items/{item_id}")
async def read_item(item_id: int):
if item_id not in items:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Item not found",
headers={"X-Error": "Item missing"},
)
return {"item": items[item_id]}
最佳实践:
- 使用标准的HTTP状态码
- 提供清晰的错误详情
- 可以通过headers传递额外信息
6. 高级查询技巧
6.1 连接查询
SQLAlchemy 2.0提供了更简洁的关系查询语法。首先定义关系:
python复制from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship, Mapped, mapped_column
class Item(Base):
__tablename__ = "items"
id: Mapped[int] = mapped_column(primary_key=True, index=True)
title: Mapped[str] = mapped_column(String(30))
description: Mapped[str] = mapped_column(String(100))
owner_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
owner: Mapped["User"] = relationship(back_populates="items")
# 在User类中添加反向引用
User.items: Mapped[list["Item"]] = relationship(back_populates="owner")
然后实现连接查询:
python复制from sqlalchemy import select
def get_user_with_items(db: Session, user_id: int):
stmt = select(User).where(User.id == user_id).options(joinedload(User.items))
return db.execute(stmt).scalars().first()
6.2 事务管理
对于需要原子性的一组操作,使用事务:
python复制def transfer_funds(db: Session, from_id: int, to_id: int, amount: float):
try:
from_account = db.get(Account, from_id)
to_account = db.get(Account, to_id)
if from_account.balance < amount:
raise ValueError("Insufficient funds")
from_account.balance -= amount
to_account.balance += amount
db.commit()
except:
db.rollback()
raise
事务使用要点:
- 明确调用
commit()或rollback() - 处理可能出现的异常
- 保持事务尽可能短小
7. 性能优化与生产准备
7.1 连接池配置
生产环境中需要优化数据库连接池:
python复制engine = create_engine(
SQLALCHEMY_DATABASE_URL,
pool_size=20,
max_overflow=10,
pool_pre_ping=True,
pool_recycle=3600
)
关键参数:
pool_size: 保持的连接数max_overflow: 允许超出的连接数pool_pre_ping: 自动检测失效连接pool_recycle: 连接回收时间(秒)
7.2 异步支持
FastAPI天生支持异步,SQLAlchemy也提供了异步API:
python复制from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
async_engine = create_async_engine(
"postgresql+asyncpg://user:password@localhost/dbname"
)
AsyncSessionLocal = sessionmaker(
async_engine, class_=AsyncSession, expire_on_commit=False
)
async def get_async_db():
async with AsyncSessionLocal() as db:
yield db
异步接口示例:
python复制@app.get("/items/{item_id}", response_model=schemas.Item)
async def read_item(item_id: int, db: AsyncSession = Depends(get_async_db)):
result = await db.execute(select(models.Item).filter(models.Item.id == item_id))
return result.scalars().first()
8. 测试与调试技巧
8.1 单元测试配置
使用pytest编写测试:
python复制import pytest
from fastapi.testclient import TestClient
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
from .main import app, get_db
from .database import Base
SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base.metadata.create_all(bind=engine)
def override_get_db():
try:
db = TestingSessionLocal()
yield db
finally:
db.close()
app.dependency_overrides[get_db] = override_get_db
client = TestClient(app)
8.2 调试SQL语句
开发时可以通过以下方式查看生成的SQL:
- 设置
echo=True:
python复制engine = create_engine(URL, echo=True)
- 使用SQLAlchemy的事件系统:
python复制from sqlalchemy import event
@event.listens_for(engine, "before_cursor_execute")
def before_cursor_execute(conn, cursor, statement, parameters, context, executemany):
print(f"SQL: {statement}")
- 使用第三方工具如SQLAlchemy-Continuum监控数据库操作
9. 部署注意事项
9.1 生产环境配置
关键的生产环境配置:
python复制app = FastAPI(
title="My API",
description="API description",
version="0.1.0",
docs_url="/api/docs", # 自定义文档路径
redoc_url=None, # 禁用Redoc
)
# 中间件配置
app.add_middleware(
CORSMiddleware,
allow_origins=["https://example.com"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
9.2 使用Gunicorn部署
对于Linux生产环境,推荐使用Gunicorn+Uvicorn:
bash复制gunicorn -w 4 -k uvicorn.workers.UvicornWorker app.main:app
Windows环境下可以考虑使用Hypercorn:
bash复制hypercorn app.main:app --bind 0.0.0.0:8000
10. 常见问题与解决方案
10.1 循环导入问题
在大型项目中,模型和工具类之间容易出现循环导入。解决方案:
- 使用
TYPE_CHECKING延迟导入:
python复制from typing import TYPE_CHECKING
if TYPE_CHECKING:
from .models import User
- 将公共类型定义放在单独文件中(如
schemas/types.py)
10.2 性能瓶颈排查
当遇到性能问题时,可以:
- 使用SQLAlchemy的
explain()分析查询计划:
python复制stmt = select(User).where(User.id == 1)
print(db.execute(stmt).explain())
- 使用FastAPI的中间件记录请求时间:
python复制@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
start_time = time.time()
response = await call_next(request)
process_time = time.time() - start_time
response.headers["X-Process-Time"] = str(process_time)
return response
- 使用Py-Spy进行性能分析:
bash复制py-spy top --pid <pid>
11. 项目结构优化建议
随着项目规模扩大,可以考虑以下优化:
- 按功能拆分模块:
code复制project/
├── apps/
│ ├── auth/
│ ├── blog/
│ └── shop/
├── core/ # 公共组件
├── static/
└── tests/
- 使用Alembic进行数据库迁移:
bash复制pip install alembic
alembic init migrations
- 实现配置分层:
python复制from pydantic import BaseSettings
class Settings(BaseSettings):
app_name: str = "My API"
database_url: str = "sqlite:///./sql_app.db"
class Config:
env_file = ".env"
settings = Settings()
12. 安全最佳实践
12.1 密码哈希
永远不要明文存储密码:
python复制from passlib.context import CryptContext
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
def get_password_hash(password: str):
return pwd_context.hash(password)
def verify_password(plain_password: str, hashed_password: str):
return pwd_context.verify(plain_password, hashed_password)
12.2 输入验证
利用Pydantic进行严格验证:
python复制from pydantic import BaseModel, EmailStr, constr
class UserCreate(BaseModel):
email: EmailStr
password: constr(min_length=8)
full_name: str | None = None
12.3 认证中间件
实现JWT认证:
python复制from fastapi.security import OAuth2PasswordBearer
from jose import JWTError, jwt
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
async def get_current_user(token: str = Depends(oauth2_scheme)):
credentials_exception = HTTPException(
status_code=401,
detail="Could not validate credentials",
headers={"WWW-Authenticate": "Bearer"},
)
try:
payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
username: str = payload.get("sub")
if username is None:
raise credentials_exception
except JWTError:
raise credentials_exception
user = get_user_by_username(db, username)
if user is None:
raise credentials_exception
return user
13. 实际项目经验分享
在最近的一个电商平台项目中,我们使用FastAPI+SQLAlchemy处理了日均100万+的API请求。以下是几个关键经验:
- 批量操作优化:对于大批量插入,使用
bulk_save_objects比单条插入快10倍以上:
python复制db.bulk_save_objects([Item(...) for _ in range(1000)])
db.commit()
- 连接池调优:根据实际负载调整连接池参数,我们的生产配置:
python复制engine = create_engine(
DATABASE_URL,
pool_size=30,
max_overflow=20,
pool_timeout=30,
pool_pre_ping=True
)
- 查询缓存策略:对热点数据实现两层缓存:
python复制from fastapi_cache import FastAPICache
from fastapi_cache.backends.redis import RedisBackend
FastAPICache.init(RedisBackend(redis_url), prefix="fastapi-cache")
- 异步任务处理:使用Celery处理耗时操作:
python复制@app.post("/send-email")
async def send_email_background(
email: EmailSchema,
background_tasks: BackgroundTasks
):
background_tasks.add_task(send_email, email)
return {"message": "Email will be sent in background"}
14. 监控与日志
14.1 结构化日志
配置JSON格式日志便于分析:
python复制import logging
from pythonjsonlogger import jsonlogger
logger = logging.getLogger("uvicorn.error")
handler = logging.StreamHandler()
formatter = jsonlogger.JsonFormatter(
"%(asctime)s %(levelname)s %(message)s %(module)s %(funcName)s"
)
handler.setFormatter(formatter)
logger.addHandler(handler)
14.2 Prometheus监控
集成Prometheus监控:
python复制from prometheus_fastapi_instrumentator import Instrumentator
Instrumentator().instrument(app).expose(app)
关键指标包括:
- 请求延迟
- 错误率
- 数据库查询时间
- 系统资源使用率
15. 扩展与集成
15.1 集成第三方服务
以发送邮件为例:
python复制import smtplib
from email.mime.text import MIMEText
def send_email(to: str, subject: str, body: str):
msg = MIMEText(body)
msg["Subject"] = subject
msg["To"] = to
msg["From"] = "noreply@example.com"
with smtplib.SMTP("smtp.example.com") as server:
server.login("user", "password")
server.send_message(msg)
15.2 文件上传处理
处理文件上传:
python复制from fastapi import UploadFile, File
@app.post("/upload")
async def upload_file(file: UploadFile = File(...)):
contents = await file.read()
# 处理文件内容
return {"filename": file.filename}
最佳实践:
- 限制文件大小
- 验证文件类型
- 异步处理大文件
16. 测试驱动开发实践
16.1 编写测试用例
示例用户测试:
python复制def test_create_user():
with TestClient(app) as client:
response = client.post(
"/users/",
json={"email": "test@example.com", "password": "secret"},
)
assert response.status_code == 200
assert "email" in response.json()
16.2 使用工厂模式
创建测试数据工厂:
python复制from faker import Faker
fake = Faker()
def create_user_factory(db: Session):
user_data = {
"email": fake.email(),
"password": fake.password(),
}
return crud.create_user(db=db, user=schemas.UserCreate(**user_data))
17. 文档生成与API描述
17.1 增强Swagger文档
通过装饰器添加更多信息:
python复制@app.post(
"/items/",
response_model=schemas.Item,
summary="Create an item",
description="Create a new item with all the information",
response_description="The created item",
)
async def create_item(item: schemas.ItemCreate):
...
17.2 使用OpenAPI扩展
添加自定义扩展:
python复制app = FastAPI(
openapi_tags=[
{
"name": "users",
"description": "Operations with users",
"externalDocs": {
"description": "Users external docs",
"url": "https://example.com",
},
}
]
)
18. 性能调优进阶
18.1 数据库索引优化
为常用查询添加索引:
python复制from sqlalchemy import Index
Index("idx_user_email", User.email)
Index("idx_item_title", Item.title)
18.2 查询优化技巧
- 只选择需要的列:
python复制db.query(User.id, User.name).filter(...)
- 使用子查询:
python复制subq = db.query(Item.owner_id).filter(Item.price > 100).subquery()
db.query(User).filter(User.id.in_(subq))
- 批量操作替代循环:
python复制# 不好
for item in items:
db.add(Item(**item))
# 好
db.bulk_insert_mappings(Item, items)
19. 微服务架构集成
19.1 服务间通信
使用HTTPX进行服务调用:
python复制import httpx
async def call_auth_service(token: str):
async with httpx.AsyncClient() as client:
response = await client.get(
"http://auth-service/verify",
headers={"Authorization": f"Bearer {token}"}
)
return response.json()
19.2 事件发布
集成消息队列:
python复制from confluent_kafka import Producer
producer = Producer({"bootstrap.servers": "kafka:9092"})
def publish_event(topic: str, message: dict):
producer.produce(topic, json.dumps(message).encode("utf-8"))
producer.flush()
20. 持续集成与部署
20.1 GitHub Actions配置
示例CI流程:
yaml复制name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:13
env:
POSTGRES_PASSWORD: postgres
ports: ["5432:5432"]
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: "3.9"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Run tests
env:
DATABASE_URL: postgresql://postgres:postgres@localhost:5432/test_db
run: |
pytest
20.2 Docker部署
示例Dockerfile:
dockerfile复制FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
最佳实践:
- 使用多阶段构建减小镜像大小
- 设置非root用户运行
- 配置健康检查
21. 前端集成策略
21.1 CORS配置
正确处理跨域请求:
python复制from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:3000"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
21.2 OpenAPI客户端生成
使用openapi-generator创建前端客户端:
bash复制npx @openapitools/openapi-generator-cli generate \
-i http://localhost:8000/openapi.json \
-g typescript-axios \
-o src/api
22. 国际化和本地化
22.1 多语言支持
使用gettext实现:
python复制from fastapi import Request
from fastapi.responses import JSONResponse
@app.middleware("http")
async def i18n_middleware(request: Request, call_next):
lang = request.headers.get("Accept-Language", "en")
# 设置语言环境
response = await call_next(request)
return response
22.2 本地化错误消息
自定义异常处理器:
python复制from fastapi.exceptions import RequestValidationError
@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request, exc):
errors = exc.errors()
localized_errors = []
for error in errors:
localized_errors.append({
"loc": error["loc"],
"msg": translate(error["msg"], request.state.lang),
"type": error["type"]
})
return JSONResponse(status_code=422, content={"detail": localized_errors})
23. 实时通信扩展
23.1 WebSocket集成
实现实时更新:
python复制from fastapi import WebSocket
@app.websocket("/ws")
async def websocket_endpoint(websocket: WebSocket):
await websocket.accept()
while True:
data = await websocket.receive_text()
await websocket.send_text(f"Message: {data}")
23.2 SSE(Server-Sent Events)
实现服务器推送:
python复制from fastapi import Response
from fastapi.responses import StreamingResponse
async def event_generator():
while True:
yield {"data": "update"}
await asyncio.sleep(1)
@app.get("/stream")
async def stream_updates():
return StreamingResponse(event_generator(), media_type="text/event-stream")
24. 架构设计进阶
24.1 领域驱动设计
按领域组织代码:
code复制project/
├── domains/
│ ├── auth/
│ │ ├── models.py
│ │ ├── services.py
│ │ └── routers.py
│ └── order/
│ ├── models.py
│ ├── services.py
│ └── routers.py
24.2 清洁架构
实现依赖反转:
python复制# 定义抽象仓储接口
class UserRepository(Protocol):
def get_by_id(self, id: int) -> User: ...
# 实现具体仓储
class SQLUserRepository:
def __init__(self, session: Session):
self.session = session
def get_by_id(self, id: int) -> User:
return self.session.get(User, id)
# 业务服务使用抽象
class UserService:
def __init__(self, repo: UserRepository):
self.repo = repo
25. 安全加固措施
25.1 速率限制
防止暴力破解:
python复制from fastapi import Request
from fastapi.responses import JSONResponse
from slowapi import Limiter
from slowapi.util import get_remote_address
limiter = Limiter(key_func=get_remote_address)
@app.post("/login")
@limiter.limit("5/minute")
async def login(request: Request):
...
25.2 输入净化
防止XSS攻击:
python复制from html import escape
@app.post("/comment")
async def create_comment(content: str):
safe_content = escape(content)
# 处理安全内容
26. 性能监控与分析
26.1 使用Sentry
集成错误监控:
python复制import sentry_sdk
sentry_sdk.init(
dsn="your-dsn",
traces_sample_rate=1.0,
)
@app.exception_handler(Exception)
async def sentry_exception_handler(request, exc):
with sentry_sdk.push_scope() as scope:
scope.set_context("request", {"url": str(request.url)})
sentry_sdk.capture_exception(exc)
raise exc
26.2 APM集成
使用Elastic APM:
python复制from elasticapm.contrib.starlette import make_apm_client, ElasticAPM
apm = make_apm_client({"SERVICE_NAME": "my-service"})
app.add_middleware(ElasticAPM, client=apm)
27. 测试覆盖率提升
27.1 边界测试
测试异常情况:
python复制def test_create_user_duplicate_email():
with TestClient(app) as client:
# 第一次创建成功
client.post("/users/", json={"email": "dup@test.com", "password": "secret"})
# 第二次应该失败
response = client.post(
"/users/",
json={"email": "dup@test.com", "password": "secret"}
)
assert response.status_code == 400
27.2 集成测试
测试完整流程:
python复制def test_user_workflow():
with TestClient(app) as client:
# 注册
reg = client.post("/register", json={"email": "test@test.com", "password": "secret"})
assert reg.status_code == 200
# 登录获取token
login = client.post("/login", data={"username": "test@test.com", "password": "secret"})
token = login.json()["access_token"]
# 使用token访问受保护端点
profile = client.get("/profile", headers={"Authorization": f"Bearer {token}"})
assert profile.status_code == 200
28. 文档自动化
28.1 API文档生成
使用ReDoc定制文档:
python复制app = FastAPI(redoc_url="/documentation")
@app.get("/items/", include_in_schema=False)
async def hidden_endpoint():
return {"message": "This won't appear in docs"}
28.2 生成Markdown文档
自动生成API文档:
bash复制python -m fastapi.openapi utils.py > openapi.json
npx redoc-cli bundle openapi.json -o api-docs.html
29. 缓存策略实现
29.1 请求缓存
使用cachetools:
python复制from cachetools import TTLCache
from fastapi import Request
cache = TTLCache(maxsize=100, ttl=300)
@app.get("/expensive")
async def expensive_operation(request: Request):
cache_key = f"{request.url.path}?{request.url.query}"
if cache_key in cache:
return cache[cache_key]
result = do_expensive_operation()
cache[cache_key] = result
return result
29.2 数据库缓存
使用SQLAlchemy事件:
python复制from sqlalchemy import event
cache = {}
@event.listens_for(Engine, "do_connect")
def receive_do_connect(dialect, conn_rec, cargs, cparams):
# 拦截连接建立
cache_key = f"{cparams['host']}-{cparams['database']}"
if cache_key in cache:
return cache[cache_key]
30. 项目脚手架工具
30.1 使用Cookiecutter
创建项目模板:
yaml复制project_name: "My FastAPI Project"
project_slug: "{{ cookiecutter.project_name.lower().replace(' ', '_') }}"
use_sqlalchemy: "y"
use_redis: "n"
30.2 自定义CLI工具
实现项目生成器:
python复制import click
@click.command()
@click.option("--name", prompt="Project name")
def create_project(name):
"""Generate new FastAPI project"""
click.echo(f"Creating {name}...")
# 创建目录结构
31. 调试技巧大全
31.1 交互式调试
使用pdb调试:
python复制@app.get("/debug")
async def debug_endpoint():
import pdb; pdb.set_trace() # 设置断点
return {"message": "debug"}
31.2 请求检查
打印请求详情:
python复制@app.middleware("http")
async def log_requests(request: Request, call_next):
print(f"Incoming request: {request.method} {request.url}")
print(f"Headers: {request.headers}")
response = await call_next(request)
return response
32. 数据库迁移管理
32.1 Alembic配置
初始化迁移环境:
bash复制alembic init migrations
配置alembic.ini:
ini复制[alembic]
script_location = migrations
sqlalchemy.url = postgresql://user:pass@localhost/db
32.2 生成迁移脚本
自动检测模型变更:
bash复制alembic revision --autogenerate -m "add user table"
应用迁移:
bash复制alembic upgrade head
33. 响应式编程集成
33.1 使用RxPY
实现响应式流:
python复制import rx
from rx import operators as ops
@app.get("/stream")
async def data_stream():
source = rx.interval(1).pipe(
ops.map(lambda i: {"count": i}),
ops.take(10)
)
return StreamingResponse(
source.pipe(ops.map(lambda x: f"data: {x}\n\n")),
media_type="text/event-stream"
)
33.2 事件总线
实现应用内事件:
python复制from rx.subject import Subject
event_bus = Subject()
def publish_event(event):
event_bus.on_next(event)
@app.on_event("startup")
async def startup():
event_bus.pipe(
ops.filter(lambda e: e["type"] == "user_created"),
ops.throttle_first(5)
).subscribe(notify_admin)
34. 微前端集成
34.1 服务端模板
返回HTML页面:
python复制from fastapi.responses import HTMLResponse
@app.get("/", response_class=HTMLResponse)
async def home():
return """
<html>
<head>
<title>My App</title>
<script src="/static/app.js"></script>
</head>
<body>
<div id="app"></div>
</body>
</html>
"""
34.2 静态文件服务
挂载前端资源:
python复制from fastapi.staticfiles import StaticFiles
app.mount("/static", StaticFiles(directory="
