附录二:常用命令与代码速查
日常开发翻这一页就够。
环境与启动
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_mode→from_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 |