FastAPI 参数详解:路径参数、查询参数与请求体 —— 从入门到实战

【学习记录】FastAPI 参数详解:路径参数、查询参数与请求体 ------ 从入门到实战

FastAPI 是一款现代、高性能的 Python Web 框架,凭借自动类型转换、数据验证和 OpenAPI 文档生成等特性,迅速成为 API 开发的首选。本文系统讲解 FastAPI 中三种最核心的参数传递方式------路径参数查询参数请求体,从基础用法到进阶验证,从混合使用到嵌套模型,辅以完整的代码示例和测试命令,帮助你全面掌握 FastAPI 的参数处理机制。


📌 目录

  1. [路径参数(Path Parameters)](#路径参数(Path Parameters))
    • 1.1 基础用法:类型注解自动转换
    • 1.2 进阶:使用 Path 添加验证与元数据
  2. [查询参数(Query Parameters)](#查询参数(Query Parameters))
    • 2.1 基础用法:类型注解 + 默认值
    • 2.2 必填查询参数
    • 2.3 使用 Query 添加验证和描述
    • 2.4 列表参数(多值)
    • 2.5 布尔类型参数
  3. [请求体(Request Body)](#请求体(Request Body))
    • 3.1 使用 Pydantic BaseModel 定义数据结构
    • 3.2 使用 Field 添加验证和描述
    • 3.3 在路径操作函数中使用请求体
    • 3.4 混合使用:路径参数 + 查询参数 + 请求体
    • 3.5 嵌套模型与复杂结构
  4. 完整实战示例
  5. 总结

一、路径参数(Path Parameters)

路径参数是 URL 路径的一部分,用于唯一标识资源 ,例如 /items/42 中的 42。FastAPI 通过类型注解自动解析、转换和验证路径参数,并提供 Path 类来添加额外的元数据、验证规则和文档描述。

1.1 基础用法:类型注解自动转换

只需在函数参数中声明与路径变量同名的参数,并标注类型,FastAPI 会自动:

  • 从路径中提取对应值
  • 转换为声明的类型(如 intfloatstr
  • 若转换失败或不符合类型,自动返回清晰的错误信息
python 复制代码
from fastapi import FastAPI

app = FastAPI()

@app.get("/items/{item_id}")
async def get_item(item_id: int):          # 类型注解 int
    return {"item_id": item_id, "message": f"商品 {item_id}"}

测试

bash 复制代码
# 正常访问
curl http://127.0.0.1:8000/items/42
# 输出: {"item_id":42,"message":"商品 42"}

# 类型错误
curl http://127.0.0.1:8000/items/abc
# 输出: 422 错误,提示 item_id 应为整数

1.2 进阶:使用 Path 添加验证与元数据

Path 是 FastAPI 提供的函数,用于为路径参数附加额外信息,例如:

  • 标题 (title):文档中显示的名称
  • 描述 (description):参数说明
  • 验证规则gt(大于)、ge(大于等于)、lt(小于)、le(小于等于)、regex(正则表达式)等
  • 示例值 (example):生成文档时的示例
  • 废弃标记 (deprecated)
python 复制代码
from fastapi import FastAPI, Path

app = FastAPI()

@app.get("/items/{item_id}")
async def get_item(
    item_id: int = Path(
        title="商品ID",
        description="必须是大于 0 的整数,用于唯一标识商品",
        gt=0,
        example=123
    )
):
    return {"item_id": item_id}

测试

bash 复制代码
# 传入 0 或负数,触发验证错误
curl http://127.0.0.1:8000/items/0
# 输出: 422 错误,{"detail":[{"type":"greater_than","msg":"Input should be greater than 0",...}]}

在生成的 OpenAPI 文档(/docs)中,会显示参数名称、类型、描述和示例值。


二、查询参数(Query Parameters)

查询参数是 URL 中 ? 后面以 key=value 形式传递的参数,常用于过滤、排序、分页 等可选操作。FastAPI 通过函数参数的类型注解自动识别查询参数,并支持使用 Query 类添加验证和元数据。

2.1 基础用法:类型注解 + 默认值

直接在路径操作函数中定义非路径参数,并给予默认值(可选)或没有默认值(必填)。FastAPI 会自动从查询字符串中提取同名参数。

python 复制代码
from fastapi import FastAPI

app = FastAPI()

@app.get("/items/")
async def list_items(limit: int = 10, skip: int = 0):
    return {"limit": limit, "skip": skip}

测试

bash 复制代码
# 使用自定义值
curl "http://127.0.0.1:8000/items/?limit=5&skip=10"
# 输出: {"limit":5,"skip":10}

# 不传参数,使用默认值
curl "http://127.0.0.1:8000/items/"
# 输出: {"limit":10,"skip":0}

2.2 必填查询参数

去掉默认值,则该查询参数为必填项。

python 复制代码
@app.get("/users/")
async def get_users(name: str):      # 没有默认值,必填
    return {"name": name}

测试

bash 复制代码
# 缺少必填参数
curl "http://127.0.0.1:8000/users/"
# 输出: 422 错误

# 正确
curl "http://127.0.0.1:8000/users/?name=alice"

2.3 使用 Query 类添加验证和描述

Query 用于为查询参数附加额外信息:标题、描述、默认值、验证规则(min_lengthmax_lengthregexgtgeltle)、废弃标记等。

python 复制代码
from fastapi import FastAPI, Query

app = FastAPI()

@app.get("/items/")
async def list_items(
    limit: int = Query(10, ge=1, le=100, description="每页数量"),
    skip: int = Query(0, ge=0, title="偏移量"),
    q: str = Query(None, max_length=50, regex="^[a-zA-Z0-9]+$")
):
    return {"limit": limit, "skip": skip, "q": q}

测试

bash 复制代码
# 超出范围
curl "http://127.0.0.1:8000/items/?limit=200"
# 422 错误

# 正则不匹配
curl "http://127.0.0.1:8000/items/?q=hello!"
# 422 错误

2.4 查询参数中的列表(多值)

使用 List 类型或 Querydefault 参数接收多个相同名称的参数。

python 复制代码
from typing import List
from fastapi import FastAPI, Query

app = FastAPI()

@app.get("/items/")
async def list_items(tags: List[str] = Query(["all"])):
    return {"tags": tags}

测试

bash 复制代码
curl "http://127.0.0.1:8000/items/?tags=python&tags=fastapi"
# 输出: {"tags":["python","fastapi"]}

curl "http://127.0.0.1:8000/items/"
# 输出: {"tags":["all"]}

2.5 布尔类型查询参数

布尔值支持多种真值表示:trueTrue1onyes 视为 TruefalseFalse0offno 视为 False

python 复制代码
@app.get("/users/")
async def get_users(active: bool = True):
    return {"active": active}

测试

bash 复制代码
curl "http://127.0.0.1:8000/users/?active=false"
# 输出: {"active":false}

三、请求体(Request Body)

请求体用于传输客户端向服务器发送的复杂数据,例如创建资源时的 JSON 对象。FastAPI 通过 Pydantic 模型 来声明请求体的数据结构,并自动完成解析、验证和文档生成。

3.1 使用 Pydantic BaseModel 定义数据模型

BaseModel 是 Pydantic 提供的基础类,用于定义数据结构和验证规则。

python 复制代码
from pydantic import BaseModel

class Item(BaseModel):
    name: str
    price: float
    is_available: bool = True   # 带默认值,可选字段
  • 每个属性通过类型注解声明字段类型。
  • 有默认值的字段为可选(请求时可不提供),无默认值的字段为必填。
  • 当客户端发送的 JSON 不符合类型要求时,FastAPI 会自动返回 422 错误。

3.2 使用 Field 添加验证和描述

Field 是 Pydantic 提供的函数,可为字段附加额外的元数据和验证规则:默认值、标题、描述、gtgeltlemin_lengthmax_lengthregex、示例值等。

python 复制代码
from pydantic import BaseModel, Field

class Item(BaseModel):
    name: str = Field(..., title="商品名称", max_length=50, example="智能手机")
    price: float = Field(..., gt=0, le=10000, description="价格,必须为正数且不超过10000")
    is_available: bool = Field(default=True, title="是否上架")
    tags: list[str] = Field(default=[], max_items=5)
  • ... 表示该字段是必填的(... 是 Python 的 Ellipsis 对象,Pydantic 约定用于表示没有默认值)。
  • 如果不提供默认值且不使用 ...,字段也是必填的,但推荐使用 ... 以明确表达意图。

3.3 在路径操作函数中使用请求体

只需将模型类型作为参数声明,FastAPI 就会自动从请求体中读取 JSON 并转换为该模型实例。

python 复制代码
from fastapi import FastAPI
from pydantic import BaseModel, Field

app = FastAPI()

class Item(BaseModel):
    name: str = Field(..., min_length=1, max_length=50)
    price: float = Field(..., gt=0)
    is_available: bool = True

@app.post("/items/")
async def create_item(item: Item):
    return {"message": f"商品 {item.name} 创建成功", "item": item.dict()}

测试

bash 复制代码
curl -X POST "http://127.0.0.1:8000/items/" \
  -H "Content-Type: application/json" \
  -d '{"name":"平板电脑","price":3999.99,"stock":10}'
# 输出: {"message":"商品 平板电脑 创建成功","item":{"name":"平板电脑","price":3999.99,"is_available":true}}

3.4 混合使用:路径参数 + 查询参数 + 请求体

FastAPI 能自动区分不同类型的参数:路径参数、查询参数和请求体,无需额外标记。

python 复制代码
from fastapi import FastAPI, Path, Query
from pydantic import BaseModel, Field

app = FastAPI()

class Item(BaseModel):
    name: str
    price: float = Field(..., gt=0)

@app.put("/items/{item_id}")
async def update_item(
    item_id: int = Path(..., gt=0),       # 路径参数
    q: str = Query(None, max_length=10),  # 查询参数
    item: Item = None                     # 请求体
):
    return {"item_id": item_id, "query": q, "item": item}

测试

bash 复制代码
curl -X PUT "http://127.0.0.1:8000/items/42?q=urgent" \
  -H "Content-Type: application/json" \
  -d '{"name":"游戏机","price":2999.99}'
# 输出: {"item_id":42,"query":"urgent","item":{"name":"游戏机","price":2999.99}}

3.5 嵌套模型与复杂结构

Pydantic 支持嵌套模型、列表、字典等复杂类型。

python 复制代码
from pydantic import BaseModel, Field
from typing import List

class SubItem(BaseModel):
    sub_name: str
    count: int = Field(..., ge=1)

class MainItem(BaseModel):
    id: int
    details: SubItem
    tags: List[str] = []

请求体示例

json 复制代码
{
  "id": 100,
  "details": {"sub_name": "配件", "count": 3},
  "tags": ["电子", "促销"]
}

四、完整实战示例

以下是一个整合了路径参数、查询参数、请求体,并包含完整验证和错误处理的示例:

python 复制代码
from fastapi import FastAPI, status, Path, Query
from pydantic import BaseModel, Field
from typing import Optional, List

app = FastAPI(title="商品管理API", description="演示路径参数、查询参数和请求体")

# ---------- 数据模型 ----------
class ItemCreate(BaseModel):
    name: str = Field(..., min_length=1, max_length=100, example="笔记本电脑")
    price: float = Field(..., gt=0, le=99999, example=5999.99)
    stock: int = Field(0, ge=0, description="库存数量")
    tags: List[str] = Field(default=[], max_items=10)

class ItemUpdate(BaseModel):
    name: Optional[str] = Field(None, min_length=1, max_length=100)
    price: Optional[float] = Field(None, gt=0, le=99999)
    stock: Optional[int] = Field(None, ge=0)

# ---------- 端点 ----------
@app.post("/items/", status_code=status.HTTP_201_CREATED)
async def create_item(item: ItemCreate):
    # 模拟数据库保存
    return {"message": "商品创建成功", "item": item.dict()}

@app.get("/items/{item_id}")
async def get_item(
    item_id: int = Path(..., gt=0, title="商品ID"),
    include_stock: bool = Query(False, description="是否返回库存信息")
):
    # 模拟从数据库查询
    item_data = {"id": item_id, "name": "示例商品", "price": 99.99, "stock": 10}
    if not include_stock:
        item_data.pop("stock")
    return item_data

@app.put("/items/{item_id}")
async def update_item(
    item_id: int = Path(..., gt=0),
    update_data: ItemUpdate = None,
    q: str = Query(None, max_length=20)
):
    # 模拟更新
    return {
        "item_id": item_id,
        "query": q,
        "updated_fields": update_data.dict(exclude_unset=True) if update_data else {}
    }

@app.delete("/items/{item_id}")
async def delete_item(
    item_id: int = Path(..., gt=0),
    permanent: bool = Query(False, description="是否永久删除")
):
    return {"item_id": item_id, "permanent": permanent, "message": "删除成功"}

# ---------- 高级查询:列表参数 ----------
@app.get("/search/")
async def search_items(
    q: str = Query(..., min_length=1, description="搜索关键词"),
    category: List[str] = Query([], description="分类过滤,可多个")
):
    return {"query": q, "categories": category}

测试命令示例

bash 复制代码
# 创建商品
curl -X POST "http://127.0.0.1:8000/items/" -H "Content-Type: application/json" -d '{"name":"手机","price":2999.99,"stock":50,"tags":["电子","促销"]}'

# 查询商品(不返回库存)
curl "http://127.0.0.1:8000/items/1"

# 查询商品(返回库存)
curl "http://127.0.0.1:8000/items/1?include_stock=true"

# 搜索(多分类)
curl "http://127.0.0.1:8000/search/?q=手机&category=电子&category=数码"

五、总结

参数类型 位置 典型用途 声明方式 验证工具
路径参数 URL 路径中 /{param} 资源标识(如 ID) 函数参数 + 类型注解 Path
查询参数 URL ?key=value 过滤、排序、分页 函数参数 + 默认值 Query
请求体 HTTP 请求体(JSON) 创建/更新资源 Pydantic 模型 BaseModel + Field

核心优势

  • ✅ 自动类型转换与验证,减少手动检查代码。
  • ✅ 自动生成 OpenAPI 文档(/docs),前后端联调高效。
  • ✅ 支持复杂嵌套结构,易于扩展。
  • ✅ 路径参数、查询参数、请求体可自由混合使用,框架自动区分。

掌握这三类参数,你就能轻松构建出健壮、规范、易维护的 FastAPI 应用程序。下一步可以学习 依赖注入中间件后台任务,让你的 API 更加专业。

相关推荐
陳10301 小时前
Linux:信号
linux·运维·服务器
承渊政道1 小时前
【MySQL数据库学习】(MySQL数据类型)
数据库·学习·mysql·ubuntu·bash·数据库开发·数据库系统
隔窗听雨眠1 小时前
CentOS Stream 9 服务器 Docker 部署 KaiwuDB 实战
服务器·docker·centos
WangX-西石油1 小时前
DVWA靶场Low级别Brute Force学习
学习·web安全·网络安全
段一凡-华北理工大学1 小时前
工业领域的Hadoop架构学习~系列文章08:Flink流处理引擎
人工智能·hadoop·学习·架构·flink·高炉炼铁·高炉炼铁智能化
z202305081 小时前
RDMA之DCQCN (14)
linux·服务器·网络·人工智能·ai
m0_737302581 小时前
读懂OpenClaw:开源自主AI智能体的革新与价值
服务器
海鸥-w2 小时前
前端学习python第三天笔记整理(list 列表,str字符串,tuple元组,set集合,dect,函数,类型注解)
前端·python·学习
Upsy-Daisy2 小时前
IOTA 学习笔记(六):Move 语言入门
笔记·学习