FastAPI 核心实战:精通路径参数、查询参数与数据交互

发布于:2025-09-01 ⋅ 阅读:(17) ⋅ 点赞:(0)

作为 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 原生语法,开发者无需记忆复杂的装饰器或配置规则。


网站公告

今日签到

点亮在社区的每一天
去签到