创作者: Yardon | GitHub: github.com/YardonYan | 版本: v1.0 |
RESTful 路由设计原则
RESTful API 的设计核心是把 URL 当作资源,HTTP 动词表示操作:
GET /api/users # 获取用户列表
POST /api/users # 创建用户
GET /api/users/123 # 获取单个用户
PUT /api/users/123 # 更新用户(全量)
PATCH /api/users/123 # 更新用户(部分字段)
DELETE /api/users/123 # 删除用户
URL 用名词复数(users),动词用 HTTP method,不要在 URL 里写 getUser 之类的东西。
路径参数与查询参数
python
from fastapi import FastAPI, Query
from enum import Enum
app = FastAPI()
class StatusEnum(str, Enum):
active = "active"
inactive = "inactive"
@app.get("/users/{user_id}")
async def get_user(
user_id: int, # 路径参数
include_posts: bool = False, # 查询参数 ?include_posts=true
status: StatusEnum = StatusEnum.active, # 枚举参数
page: int = Query(1, ge=1), # 页码,最小1
size: int = Query(20, ge=1, le=100), # 每页条数,1-100
q: str | None = Query(None, min_length=2, description="搜索关键词"),
):
"""获取用户详情"""
skip = (page - 1) * size
# ... 数据库查询
return {"user_id": user_id, "page": page, "q": q}
Query 装饰器提供了参数校验和文档描述。ge(greater or equal)、le(less or equal)确保传入值在合法范围内。
路径参数 vs 查询参数:如何选?
路径参数 (/users/123) |
查询参数 (?page=2) |
|---|---|
| 表示"哪个资源" | 表示"怎么筛选/排序" |
| 通常是唯一标识 | 可选,用于过滤/分页 |
| 必填 | 可选(有默认值) |
请求体:Pydantic 模型进阶
python
from pydantic import BaseModel, Field, EmailStr, field_validator
from datetime import date
from typing import Optional
class UserCreate(BaseModel):
"""创建用户时的请求体"""
username: str = Field(..., min_length=3, max_length=50, description="用户名")
email: EmailStr # 自动验证邮箱格式
password: str = Field(..., min_length=8)
bio: Optional[str] = Field(None, max_length=200)
birth_date: Optional[date] = None
@field_validator("username")
@classmethod
def username_no_special_chars(cls, v: str) -> str:
if not v.replace("_", "").replace("-", "").isalnum():
raise ValueError("用户名只能包含字母、数字、下划线和连字符")
return v.strip()
@field_validator("password")
@classmethod
def password_strong_enough(cls, v: str) -> str:
if not any(c.isdigit() for c in v):
raise ValueError("密码必须包含至少一个数字")
return v
@app.post("/users", status_code=201)
async def create_user(user: UserCreate):
# user 已经被验证、转换完毕
# 这里 user.username 已经被 strip 过了,email 格式已验证
return {"id": 1234, "username": user.username}
@field_validator 可以编写复杂的自定义校验逻辑。比传统手写 if/else 清晰一百倍。
响应模型:控制输出
python
from pydantic import BaseModel
class UserResponse(BaseModel):
"""对外输出的用户模型------绝不含 password"""
id: int
username: str
email: str
bio: str | None = None
model_config = {"from_attributes": True} # 允许从 ORM 对象转换
@app.get("/users/{user_id}", response_model=UserResponse)
async def get_user(user_id: int):
user = await db.query(...)
return user # FastAPI 自动过滤掉 password 等敏感字段
response_model 就是你的安全检查门------数据库返回了 20 个字段,但前端只能看到你声明的 5 个。
错误处理与状态码
python
from fastapi import HTTPException
@app.get("/users/{user_id}")
async def get_user(user_id: int):
user = await find_user(user_id)
if not user:
raise HTTPException(status_code=404, detail=f"用户 {user_id} 不存在")
return user
# 全局异常处理器
from fastapi import Request
from fastapi.responses import JSONResponse
@app.exception_handler(ValueError)
async def value_error_handler(request: Request, exc: ValueError):
return JSONResponse(status_code=400, content={"detail": str(exc)})
路由分组与 API 版本管理
随着应用变大,main.py 里塞满 50 个路由函数会变成噩梦。FastAPI 提供了 APIRouter 来分组:
python
# routers/users.py
from fastapi import APIRouter
router = APIRouter(prefix="/api/v1/users", tags=["用户管理"])
@router.get("/")
async def list_users(): ...
@router.post("/")
async def create_user(): ...
@router.get("/{user_id}")
async def get_user(user_id: int): ...
python
# main.py
from routers import users, posts, auth
app = FastAPI()
app.include_router(users.router)
app.include_router(posts.router)
app.include_router(auth.router)
文件上传与静态文件
python
from fastapi import UploadFile, File
@app.post("/upload")
async def upload_file(file: UploadFile = File(...)):
# 不把整个文件读入内存------适合大文件
contents = await file.read()
with open(f"uploads/{file.filename}", "wb") as f:
f.write(contents)
return {"filename": file.filename, "size": len(contents)}
本章小结
| 概念 | 要点 |
|---|---|
| 路径参数 | /users/{id} 表示资源,需精确匹配 |
| 查询参数 | ?page=2 表示过滤/分页,用 Query() 校验 |
| Pydantic | 请求体验证、响应过滤、字段级校验链 |
| APIRouter | 按模块拆分路由,方便扩展 |
下一章:数据库与 ORM------用 SQLAlchemy 把数据持久化。
📌 创作者: Yardon | 🏠 个人网站: GlimmerAI.top
📖 本章是「FastAPI 全栈后端 」系列的第 2 章。下一章:数据库与ORM
🌟 欢迎大家来观看!