FastAPI 核心实战:精通路径参数、查询参数与数据交互
作为 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.pyfrom fastapi import FastAPIapp = 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 Pathfrom 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, # 可选参数:默认值为 1limit: int = 10, # 可选参数:默认值为 10category: 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.pyfrom pydantic import BaseModel, Fieldfrom 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.pyfrom 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 # 模拟生成商品 IDreturn {"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.pyclass 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 = Trueschema_extra = {"example": {"id": 1001,"name": "无线蓝牙耳机","price": 199.9,"stock": 50,"is_active": True}}
2. 使用响应体约束返回格式
通过 response_model 参数指定响应体模型,FastAPI 会自动:
(1)过滤掉模型中未定义的字段(避免泄露敏感数据)
(2)验证返回数据的类型和规则
(3)在文档中显示响应体结构
# main.pyfrom 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, Queryfrom schemas import ItemCreate, ItemResponsefrom typing import List, Optionalapp = 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) * limitend = start + limitfiltered = 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 itemreturn {"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) + 1fake_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_idfake_items_db[i] = updated_itemreturn updated_itemreturn {"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 原生语法,开发者无需记忆复杂的装饰器或配置规则。