路由整合

把 Pydantic 模型和 CRUD 函数串到 FastAPI 路由里。

一、项目结构

03-增删改查CRUD/
├── 01-Pydantic模型.md    ← schemas.py
├── 02-CRUD操作.md        ← crud.py
└── 03-路由整合.md        ← main.py(你在这里)

对应的代码文件:

schemas.py   — 请求/响应模型
crud.py      — 数据库操作函数
main.py      — 路由 + 依赖注入
models.py    — 数据模型(沿用 01 的)
database.py  — 数据库配置(沿用 01 的)

二、完整代码

from fastapi import FastAPI, Depends, HTTPException
from sqlalchemy.orm import Session
from database import SessionLocal, engine, Base
from schemas import UserCreate, UserUpdate, UserOut, UserListOut
import crud

# 建表
Base.metadata.create_all(bind=engine)

app = FastAPI()


# ---------- 依赖注入(和 01 一样)----------
def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()


# ---------- 创建用户 ----------
@app.post("/users/", response_model=UserOut)
def create_user(user_in: UserCreate, db: Session = Depends(get_db)):
    return crud.create_user(db=db, user_in=user_in)


# ---------- 查询用户列表 ----------
@app.get("/users/", response_model=UserListOut)
def list_users(skip: int = 0, limit: int = 10, db: Session = Depends(get_db)):
    total = crud.count_users(db)
    items = crud.get_users(db, skip=skip, limit=limit)
    return {"total": total, "items": items}


# ---------- 查询单个用户 ----------
@app.get("/users/{user_id}", response_model=UserOut)
def get_user(user_id: int, db: Session = Depends(get_db)):
    user = crud.get_user(db, user_id=user_id)
    if not user:
        raise HTTPException(status_code=404, detail="用户不存在")
    return user


# ---------- 更新用户 ----------
@app.patch("/users/{user_id}", response_model=UserOut)
def update_user(user_id: int, user_in: UserUpdate, db: Session = Depends(get_db)):
    user = crud.update_user(db, user_id=user_id, user_in=user_in)
    if not user:
        raise HTTPException(status_code=404, detail="用户不存在")
    return user


# ---------- 删除用户 ----------
@app.delete("/users/{user_id}")
def delete_user(user_id: int, db: Session = Depends(get_db)):
    success = crud.delete_user(db, user_id=user_id)
    if not success:
        raise HTTPException(status_code=404, detail="用户不存在")
    return {"detail": "删除成功"}

三、逐块解释

1. response_model

@app.post("/users/", response_model=UserOut)
  • FastAPI 自动用 UserOut 校验和过滤响应数据
  • 即使 CRUD 函数返回的是完整的 ORM 对象,响应里也只包含 UserOut 中定义的字段
  • Swagger 文档也会自动显示 UserOut 的字段结构

2. HTTPException

if not user:
    raise HTTPException(status_code=404, detail="用户不存在")
  • 返回标准的 HTTP 错误响应
  • status_code:HTTP 状态码
  • detail:错误描述,前端可以直接展示给用户

3. 请求方法选择

方法语义示例
POST创建资源POST /users/
GET查询资源GET /users/GET /users/1
PATCH部分更新PATCH /users/1(只传要改的字段)
PUT整体替换PUT /users/1(传全部字段)
DELETE删除资源DELETE /users/1

更新用 PATCH 还是 PUT

  • PATCH:只更新传了的字段,没传的不动(更常用)
  • PUT:全部字段都传,没传的会被覆盖为默认值

四、运行测试

uvicorn main:app --reload

打开 http://127.0.0.1:8000/docs 测试:

1. POST /users/         创建一个用户
2. GET  /users/         查看用户列表
3. GET  /users/1        查看单个用户
4. PATCH /users/1       修改用户
5. DELETE /users/1      删除用户

五、完整调用链路

前端请求

main.py(路由)     →  参数校验(Pydantic)

crud.py(操作)     →  数据库读写(SQLAlchemy)

models.py(模型)   →  映射到数据库表

数据库

models.py → crud.py → main.py → Pydantic 过滤字段 → 返回前端