跳到主要内容

附录二:常用命令与代码速查

日常开发翻这一页就够。

环境与启动

python -m venv venv # 创建虚拟环境
venv\Scripts\Activate.ps1 # 激活(Windows PowerShell)
source venv/bin/activate # 激活(Mac/Linux)
pip install -r requirements.txt # 安装依赖
pip freeze > requirements.txt # 导出依赖

fastapi dev app/main.py # 开发启动(热重载)
fastapi dev app/main.py --port 8001 # 换端口
fastapi run app/main.py --workers 4 # 生产启动(多进程)
uvicorn app.main:app --reload # 等价的老写法

常用地址:接口 http://127.0.0.1:8000 | 文档 /docs | 备用文档 /redoc

FastAPI 速查

from typing import Annotated
from fastapi import FastAPI, APIRouter, Depends, HTTPException, Query, Path, status

# 路由注册
@app.get("/items/{item_id}") # 路径参数
def f(item_id: int, q: str | None = None): # 无默认值=必填查询参数;有=可选
...

# 参数校验
page: Annotated[int, Query(ge=1)] = 1
name: Annotated[str, Query(min_length=1, max_length=50)]
user_id: Annotated[int, Path(ge=1)]

# 请求体
class ItemCreate(BaseModel):
name: str = Field(min_length=1, max_length=100)

@app.post("/items", response_model=ItemOut, status_code=status.HTTP_201_CREATED)
def create(item: ItemCreate): ...

# 错误
raise HTTPException(status_code=404, detail="不存在")
# 401 没登录 / 403 没权限 / 404 不存在 / 409 冲突 / 422 校验失败(自动)

# 依赖注入
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()

SessionDep = Annotated[Session, Depends(get_db)]

# 路由拆分
router = APIRouter(prefix="/users", tags=["用户"])
app.include_router(router)

# 生命周期
@asynccontextmanager
async def lifespan(app: FastAPI):
... # 启动时
yield
... # 关闭时
app = FastAPI(lifespan=lifespan)

Pydantic v2 速查

from pydantic import BaseModel, ConfigDict, EmailStr, Field

class UserOut(BaseModel):
model_config = ConfigDict(from_attributes=True) # 允许从 ORM 对象读取
id: int
email: EmailStr

m.model_dump() # → dict
m.model_dump(exclude_unset=True) # 只含实际传入的字段(部分更新用)
m.model_dump_json() # → JSON 字符串
Model.model_validate(obj) # 从 dict/对象 创建

v1 → v2 对照:.dict()model_dump()orm_modefrom_attributes@validator@field_validator

SQLAlchemy 2.0 速查

from sqlalchemy import create_engine, select, func, or_, ForeignKey, String
from sqlalchemy.orm import (DeclarativeBase, Mapped, mapped_column,
relationship, sessionmaker, selectinload, Session)

# 连接
engine = create_engine("sqlite:///./app.db",
connect_args={"check_same_thread": False}) # SQLite 专用参数
SessionLocal = sessionmaker(bind=engine, autoflush=False)
Base.metadata.create_all(engine) # 建表(不改表!)

# 模型
class User(Base):
__tablename__ = "users"
id: Mapped[int] = mapped_column(primary_key=True)
name: Mapped[str] = mapped_column(String(50), unique=True, index=True)
age: Mapped[int | None] # 可空
posts: Mapped[list["Post"]] = relationship(back_populates="author")

class Post(Base):
__tablename__ = "posts"
id: Mapped[int] = mapped_column(primary_key=True)
author_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
author: Mapped["User"] = relationship(back_populates="posts")

# 增
db.add(obj); db.commit(); db.refresh(obj)

# 查
db.get(User, 1) # 按主键
db.scalars(select(User)).all() # 全部
db.scalars(select(User).where(User.age >= 18)).first() # 条件+第一条
select(User).where(or_(A, B)) # OR
select(User).where(User.name.like("%小%")) # 模糊
select(User).order_by(User.id.desc()).offset(10).limit(10) # 排序分页
db.scalar(select(func.count()).select_from(User)) # 计数
select(Post).options(selectinload(Post.author)) # 预加载防 N+1
select(Post).where(Post.tags.any(Tag.name == "python")) # 多对多过滤

# 改:查出来直接改属性
user.name = "新名字"; db.commit()

# 删
db.delete(obj); db.commit()

Alembic 速查

alembic init alembic # 初始化(一次)
alembic revision --autogenerate -m "描述" # 生成迁移(记得人工检查!)
alembic upgrade head # 应用到最新
alembic downgrade -1 # 回退一版
alembic current / history # 当前版本 / 历史

测试速查

pytest -v # 全部用例
pytest -x # 失败即停
pytest -k "关键词" # 按名字筛选
from fastapi.testclient import TestClient
client = TestClient(app)
resp = client.post("/users", json={...}) # JSON 请求体
resp = client.post("/login", data={...}) # 表单
resp = client.get("/me", headers={"Authorization": f"Bearer {token}"})
app.dependency_overrides[get_db] = override_get_db # 替换依赖

数据库连接字符串

"sqlite:///./app.db" # SQLite 文件
"sqlite://" # SQLite 内存(测试)
"mysql+pymysql://user:pass@localhost:3306/dbname" # MySQL (pip install pymysql)
"postgresql+psycopg2://user:pass@localhost:5432/dbname" # PostgreSQL (pip install psycopg2-binary)

HTTP 状态码速记

场景场景
200成功401没登录
201创建成功403没权限
204删除成功无内容404不存在
400业务性错误409冲突(重名等)
422校验失败(自动)500代码有 bug