作为 Python 生态中最热门的现代 API 框架,FastAPI 凭借类型提示驱动的开发模式、自动生成的交互式文档和媲美 Node.js 的性能,成为后端开发者的首选工具。本文将深入讲解 FastAPI 中最核心的数据交互模块 —— 路径参数、查询参数、请求体与响应体,结合参数验证和示例数据,帮你构建健壮、规范的 API 服务。
一、环境准备:开启 FastAPI 之旅
在开始前,需先搭建基础开发环境。FastAPI 依赖 ASGI 服务器(如 Uvicorn)运行,同时推荐使用 Pydantic 处理数据验证(FastAPI 已内置):
# 安装核心依赖
pip install fastapi uvicorn pydantic
创建项目结构(推荐如下):
fastapi-demo/
├── main.py # 主程序入口
└── schemas.py # 数据模型定义(Pydantic Models)
运行方式:
# 开发模式(代码修改自动重启)
uvicorn main:app --reload --host 0.0.0.0 --port 8000
启动后,FastAPI 会自动生成两个交互式文档:
(1)Swagger UI:http://localhost:8000/docs(支持在线调试)
(2)ReDoc:http://localhost:8000/redoc(更简洁的文档展示)
二、路径参数:定位资源的核心标识
路径参数(Path Parameters)用于从 URL 路径中提取资源标识(如用户 ID、商品 ID),是 RESTful API 设计的基础。
1. 基础用法:动态提取路径值
通过在路由路径中使用 {参数名} 定义路径参数,FastAPI 会自动解析并转换为指定类型:
# main.py
from fastapi import FastAPI
app = FastAPI(title="FastAPI 核心参数实战", version="1.0")
# 路径参数示例:获取单个商品信息
@app.get("/items/{item_id}")
async def get_item(item_id: int): # 类型提示指定参数类型为 int
"""根据商品 ID 获取商品信息"""
return {
"status": "success",
"data": {"item_id": item_id, "message": f"获取 ID 为 {item_id} 的商品成功"}
}
关键特性:
(1)自动类型转换:若请求 GET /items/abc(非 int 类型),FastAPI 会返回 422 Unprocessable Entity 错误,无需手动判断。
(2)自动文档生成:在 Swagger UI 中,路径参数会被自动标记为必填项,并显示类型说明。
2. 高级用法:路径参数验证与约束
当需要对路径参数进行更精细的控制(如取值范围、长度限制)时,可使用 Path 类添加验证规则:
from fastapi import Path
from typing import Optional
# 路径参数验证:商品 ID 必须大于 0 且小于 1000
@app.get("/items/{item_id}/details")
async def get_item_details(
# gt:大于(greater than),lt:小于(less than),description:文档说明
item_id: int = Path(..., gt=0, lt=1000, description="商品 ID(1-999 之间)")
):
return {
"status": "success",
"data": {"item_id": item_id, "details": "商品详细信息..."}
}
常用验证参数:
(1)gt/ge:大于 / 大于等于
(2)lt/le:小于 / 小于等于
(3)min_length/max_length:字符串长度限制(适用于 str 类型参数)
(4)regex:正则表达式匹配(如 regex=r"^[A-Za-z0-9]+$")
三、查询参数:过滤与筛选资源的灵活工具
查询参数(Query Parameters)用于对资源进行过滤、分页或筛选(如 ?page=1&limit=10),FastAPI 会自动识别函数中未在路径中定义的参数作为查询参数。
1. 基础用法:可选与必填查询参数
通过设置默认值,可区分 “可选查询参数” 和 “必填查询参数”:
# 查询参数示例:分页获取商品列表
@app.get("/items")
async def get_item_list(
page: int = 1, # 可选参数:默认值为 1
limit: int = 10, # 可选参数:默认值为 10
category: Optional[str] = None # 可选参数:允许为 None(需导入 Optional)
):
"""分页获取商品列表,支持按分类筛选"""
return {
"status": "success",
"data": {
"page": page,
"limit": limit,
"category": category,
"items": ["商品1", "商品2"] # 模拟数据
}
}
请求示例:
(1)GET /items → 使用默认值(page=1,limit=10,category=None)
(2)GET /items?page=2&limit=20 → 自定义分页参数
(3)GET /items?category=electronics → 按分类筛选
2. 高级用法:查询参数验证
与路径参数类似,使用 Query 类可添加查询参数的验证规则:
from fastapi import Query
# 查询参数验证:分页参数与分类筛选
@app.get("/items/filtered")
async def get_filtered_items(
# page 必须 ≥1,limit 必须在 1-100 之间
page: int = Query(1, ge=1, description="页码(从 1 开始)"),
limit: int = Query(10, ge=1, le=100, description="每页数量(1-100)"),
# category 可选,但如果提供需满足长度要求
category: Optional[str] = Query(None, min_length=2, max_length=20)
):
return {
"status": "success",
"data": {"page": page, "limit": limit, "category": category}
}
四、请求体:传递复杂数据的核心载体
对于 POST、PUT 等请求,需要通过请求体(Request Body)传递复杂数据(如创建用户的表单信息、JSON 数据)。FastAPI 基于 Pydantic 模型定义请求体结构,自动完成数据验证和类型转换。
1. 定义请求体模型(Pydantic Model)
首先在定义 Pydantic 模型,描述请求体的结构和字段规则:
# schemas.py
from pydantic import BaseModel, Field
from typing import Optional
# 商品创建请求体模型
class ItemCreate(BaseModel):
name: str = Field(..., min_length=2, max_length=50, description="商品名称")
price: float = Field(..., gt=0, description="商品价格(必须大于 0)")
stock: int = Field(10, ge=0, description="库存数量(默认 10,≥0)")
is_active: Optional[bool] = Field(True, description="是否上架(默认 True)")
# 配置示例数据(用于文档展示)
class Config:
schema_extra = {
"example": {
"name": "无线蓝牙耳机",
"price": 199.9,
"stock": 50,
"is_active": True
}
}
关键说明:
(1)继承 BaseModel 即可创建 Pydantic 模型
(2)Field 类用于添加字段验证规则(类似 Path/Query)
(3)Config.schema_extra 用于定义示例数据,在 Swagger UI 中会显示
2. 使用请求体处理 POST 请求
在路由函数中直接使用 Pydantic 模型作为参数,FastAPI 会自动解析请求体(默认支持 JSON 格式):
# main.py
from schemas import ItemCreate
# POST 请求:创建商品(使用请求体)
@app.post("/items", summary="创建新商品", response_description="创建成功的商品信息")
async def create_item(item: ItemCreate):
"""
创建新商品:
- **name**: 商品名称(2-50 字符)
- **price**: 商品价格(>0)
- **stock**: 库存数量(默认 10,≥0)
- **is_active**: 是否上架(默认 True)
"""
# 模拟数据库操作(实际项目中会写入数据库)
item_dict = item.dict() # 将 Pydantic 模型转换为字典
item_dict["id"] = 1001 # 模拟生成商品 ID
return {
"status": "success",
"data": item_dict
}
请求示例(JSON 格式):
{
"name": "无线蓝牙耳机",
"price": 199.9,
"stock": 50,
"is_active": true
}
自动验证特性:
(1)若 price 为负数,会返回 422 错误
(2)若缺少必填字段 name,会提示 “field required”
五、响应体:规范 API 的返回格式
响应体(Response Body)用于定义 API 的返回结构,通过 Pydantic 模型可强制规范返回数据格式,避免接口返回混乱。
1. 定义响应体模型
定义响应体模型,区分 “创建响应” 和 “详情响应”(按需设计):
# schemas.py
class ItemResponse(BaseModel):
"""商品详情响应模型"""
id: int = Field(..., description="商品 ID")
name: str = Field(..., description="商品名称")
price: float = Field(..., description="商品价格")
stock: int = Field(..., description="库存数量")
is_active: bool = Field(..., description="是否上架")
class Config:
# 允许从 ORM 对象(如 SQLAlchemy 模型)转换为 Pydantic 模型
orm_mode = True
schema_extra = {
"example": {
"id": 1001,
"name": "无线蓝牙耳机",
"price": 199.9,
"stock": 50,
"is_active": True
}
}
2. 使用响应体约束返回格式
通过 response_model 参数指定响应体模型,FastAPI 会自动:
(1)过滤掉模型中未定义的字段(避免泄露敏感数据)
(2)验证返回数据的类型和规则
(3)在文档中显示响应体结构
# main.py
from schemas import ItemResponse
# 用响应体模型约束返回格式
@app.get("/items/{item_id}/response", response_model=ItemResponse)
async def get_item_with_response(item_id: int = Path(..., gt=0, lt=1000)):
"""返回规范格式的商品详情(使用 response_model)"""
# 模拟数据库查询结果
return {
"id": item_id,
"name": "无线蓝牙耳机",
"price": 199.9,
"stock": 50,
"is_active": True,
"secret_field": "敏感数据" # 会被自动过滤(响应模型中无该字段)
}
六、综合实战:构建完整的商品 API
结合上述所有知识点,构建一个支持 “增删改查” 的商品 API,涵盖路径参数、查询参数、请求体、响应体和参数验证:
# main.py 完整代码
from fastapi import FastAPI, Path, Query
from schemas import ItemCreate, ItemResponse
from typing import List, Optional
app = FastAPI(title="FastAPI 商品 API", version="1.0")
# 模拟数据库(实际项目中替换为真实数据库)
fake_items_db = [
{"id": 1, "name": "iPhone 15", "price": 5999.0, "stock": 20, "is_active": True},
{"id": 2, "name": "MacBook Pro", "price": 12999.0, "stock": 10, "is_active": True}
]
# 1. 获取商品列表(带分页和筛选)
@app.get("/items", response_model=List[ItemResponse], summary="获取商品列表")
async def get_items(
page: int = Query(1, ge=1),
limit: int = Query(10, ge=1, le=100),
category: Optional[str] = None
):
start = (page - 1) * limit
end = start + limit
filtered = fake_items_db[start:end]
return filtered
# 2. 获取单个商品
@app.get("/items/{item_id}", response_model=ItemResponse, summary="获取商品详情")
async def get_item(item_id: int = Path(..., gt=0)):
for item in fake_items_db:
if item["id"] == item_id:
return item
return {"detail": "商品不存在"} # FastAPI 会自动转换为 404 错误
# 3. 创建商品
@app.post("/items", response_model=ItemResponse, summary="创建商品")
async def create_item(item: ItemCreate):
new_item = item.dict()
new_item["id"] = len(fake_items_db) + 1
fake_items_db.append(new_item)
return new_item
# 4. 更新商品
@app.put("/items/{item_id}", response_model=ItemResponse, summary="更新商品")
async def update_item(
item_id: int = Path(..., gt=0),
item: ItemCreate
):
for i, existing_item in enumerate(fake_items_db):
if existing_item["id"] == item_id:
updated_item = item.dict()
updated_item["id"] = item_id
fake_items_db[i] = updated_item
return updated_item
return {"detail": "商品不存在"}
# 5. 删除商品
@app.delete("/items/{item_id}", summary="删除商品")
async def delete_item(item_id: int = Path(..., gt=0)):
for i, item in enumerate(fake_items_db):
if item["id"] == item_id:
fake_items_db.pop(i)
return {"status": "success", "message": "商品已删除"}
return {"detail": "商品不存在"}
七、总结:FastAPI 数据交互的核心优势
(1)类型提示驱动:通过 Python 类型提示实现参数解析和验证,减少重复代码。
(2)自动文档生成:无需额外配置,自动生成 Swagger UI 和 ReDoc 文档,降低协作成本。
(3)强大的数据验证:基于 Pydantic 实现字段级验证,支持复杂规则(如范围、正则、长度)。
(4)规范的响应格式:通过 response_model 强制约束返回结构,避免接口返回混乱。
(5)低学习成本:贴近 Python 原生语法,开发者无需记忆复杂的装饰器或配置规则。