目录
[二、FastAPI 介绍](#二、FastAPI 介绍)
[2.1 FastAPI 是什么](#2.1 FastAPI 是什么)
[2.2 FastAPI 特点](#2.2 FastAPI 特点)
[2.3 FastAPI 适用场景](#2.3 FastAPI 适用场景)
[2.4 FastAPI 技术栈](#2.4 FastAPI 技术栈)
[2.5 为什么选择 FastAPI](#2.5 为什么选择 FastAPI)
[三、FastAPI 安装与基本使用](#三、FastAPI 安装与基本使用)
[3.1 前置准备](#3.1 前置准备)
[3.1.1 版本检查](#3.1.1 版本检查)
[3.1.2 创建虚拟环境](#3.1.2 创建虚拟环境)
[3.1.3 安装 FastAPI](#3.1.3 安装 FastAPI)
[3.1.4 安装 Uvicorn](#3.1.4 安装 Uvicorn)
[3.2 FastAPI使用](#3.2 FastAPI使用)
[3.2.1 第一个 FastAPI 程序](#3.2.1 第一个 FastAPI 程序)
[3.2.2 启动服务](#3.2.2 启动服务)
[3.2.3 接口效果验证](#3.2.3 接口效果验证)
[3.2.4 接口文档](#3.2.4 接口文档)
[3.2.5 使用FastAPI CLI 启动服务](#3.2.5 使用FastAPI CLI 启动服务)
[3.2.6 使用uvicorn 启动](#3.2.6 使用uvicorn 启动)
[四、FastAPI 接口请求参数使用](#四、FastAPI 接口请求参数使用)
[4.1 接口参数](#4.1 接口参数)
[4.1.1 接口参数说明](#4.1.1 接口参数说明)
[4.1.2 接口参数分类](#4.1.2 接口参数分类)
[4.2 路径参数](#4.2 路径参数)
[4.2.1 路径参数类型](#4.2.1 路径参数类型)
[4.2.2 路径顺序](#4.2.2 路径顺序)
[4.2.3 预设值的路径参数(Enum)](#4.2.3 预设值的路径参数(Enum))
[4.2.4 包含路径的路径参数](#4.2.4 包含路径的路径参数)
[4.3 查询参数](#4.3 查询参数)
[4.3.1 基本用法](#4.3.1 基本用法)
[4.3.2 必选查询参数](#4.3.2 必选查询参数)
[4.3.3 参数混合使用](#4.3.3 参数混合使用)
[4.4 查询参数校验](#4.4 查询参数校验)
[4.4.1 参数基本校验](#4.4.1 参数基本校验)
[4.4.2 同时添加更多参数校验](#4.4.2 同时添加更多参数校验)
[4.4.3 带默认值的校验](#4.4.3 带默认值的校验)
[4.4.4 必填参数](#4.4.4 必填参数)
[4.5 路径参数值校验](#4.5 路径参数值校验)
[4.5.1 Path导入](#4.5.1 Path导入)
[4.5.2 Path 校验参数说明](#4.5.2 Path 校验参数说明)
[4.5.3 数值组合校验](#4.5.3 数值组合校验)
[4.5.4 路径参数与查询参数混合使用](#4.5.4 路径参数与查询参数混合使用)
[4.5.5 小结](#4.5.5 小结)
[4.6 请求体参数](#4.6 请求体参数)
[4.6.1 什么是请求体参数](#4.6.1 什么是请求体参数)
[4.6.2 请求体与查询参数的区别](#4.6.2 请求体与查询参数的区别)
[4.6.3 使用 Pydantic 模型声明请求体](#4.6.3 使用 Pydantic 模型声明请求体)
[4.6.4 请求体参数-类型注解Field](#4.6.4 请求体参数-类型注解Field)
[4.6.5 请求体 + 路径参数 + 查询参数混合](#4.6.5 请求体 + 路径参数 + 查询参数混合)
[4.6.6 小结](#4.6.6 小结)
一、前言
在微服务开发中,通常需要服务端提供接口给前端,接口将来自各处的数据汇总在一起返回给页面做展示,在Python 中有很多种WEB框架可以构建API接口,本文以比较热门的FastAPI 为例进行说明。
二、FastAPI 介绍
2.1 FastAPI 是什么
FastAPI 是一个用于构建 API 的现代、快速(高性能)的 Python Web 框架,专为构建 RESTful API 而设计。官网:FastAPI - FastAPI
- FastAPI 使用 Python 3.8+ 并基于标准的 Python 类型提示,使用 Starlette 和 Pydantic 构建,能够自动生成 API 文档并进行数据校验。

2.2 FastAPI 特点
FastAPI 之所以在 Python Web 框架中脱颖而出,主要得益于以下特点:
-
高性能
- 基于 Starlette 和 Pydantic,性能与 NodeJS 和 Go 相当,是最快的 Python 框架之一
-
快速开发
- 开发速度提升约 200%-300%,标准类型声明即可完成数据校验和文档生成
-
减少错误
- 减少约 40% 的人为错误,类型系统自动捕获常见问题
-
自动生成文档
- 自动生成交互式 API 文档(Swagger UI 和 ReDoc),无需手动维护
-
类型安全
- 基于标准 Python 类型提示,编辑器提供全面的自动补全和错误检查
-
异步支持
- 原生支持 async/await,可高效处理 IO 密集型任务
2.3 FastAPI 适用场景
在下面的一些开发场景中可以考虑使用FastAPI
-
构建 API 后端
- 用于构建 RESTful API,支持前后端分离的 Web 应用
-
微服务架构
- 轻量高效,适合作为微服务后端框架
-
数据处理 API
- 适用于接收和返回 JSON 数据的数据处理服务
-
实时通信
- 支持 WebSocket,适用于实时通信场景
-
机器学习服务
- 可将训练好的模型封装为 API,方便前端和其他服务调用
2.4 FastAPI 技术栈
FastAPI 构建在两个核心库之上:
-
FastAPI 是 Starlette 的子类,因此你可以使用 Starlette 的所有功能
-
同时 FastAPI 完全兼容 Pydantic,包括基于 Pydantic 的 ORM(如 SQLModel)等外部库
|---------------|----------|-------------------------------------------------------|
| 组件 | 作用 | 说明 |
| Starlette | Web 框架层 | 提供路由、中间件、WebSocket 等基础 Web 功能,FastAPI 直接继承自 Starlette |
| Pydantic | 数据校验层 | 基于 Python 类型提示进行数据校验、序列化和文档生成 |
| Uvicorn | ASGI 服务器 | 基于 uvloop 和 httptools 的高性能 ASGI 服务器,用于运行 FastAPI 应用 |
2.5 为什么选择 FastAPI
FastAPI 作为一款优秀的WEB框架,相对其他框架有很多优点,下面多维度对比了其他Python框架的特点
|------|------------------------|------------|------------|
| 对比维度 | FastAPI | Flask | Django |
| 性能 | 高(异步,ASGI) | 中(同步,WSGI) | 中(同步,WSGI) |
| 自动文档 | 内置(Swagger UI + ReDoc) | 需第三方扩展 | 需第三方扩展 |
| 类型校验 | 内置(Pydantic) | 需手动实现 | 需手动实现 |
| 异步支持 | 原生支持 | 需扩展 | 3.1+ 支持 |
| 学习曲线 | 低 | 低 | 较高 |
| 适用规模 | 中小型 / 微服务 | 中小型 | 大型 / 全栈 |
三、FastAPI 安装与基本使用
3.1 前置准备
3.1.1 版本检查
FastAPI 依赖 Python 3.8 及更高版本,因此首先要检查你本地的Python 版本是否符合要求
- 如果你的 Python 版本低于 3.8,请先升级 Python

3.1.2 创建虚拟环境
推荐在虚拟环境下安装 FastAPI,避免与系统中已有的 Python 包产生冲突
- 虚拟环境是 Python 开发最佳实践,每个项目可以使用独立的虚拟环境,可避免不同项目之间的依赖冲突
bash
# 创建虚拟环境
python -m venv venv
# 激活虚拟环境(macOS/Linux)
source venv/bin/activate
# 激活虚拟环境(Windows)
venv\Scripts\activate
3.1.3 安装 FastAPI
使用 pip 命令安装 FastAPI:
bash
pip install fastapi

使用上面这条命令只安装 FastAPI 核心包,如果你需要一次性安装 FastAPI 及其所有可选依赖,可以使用下面这个命令:
bash
pip install "fastapi[all]"
fastapi[all] 会安装以下组件:
|-----------------------------|--------------------------|
| 包名 | 用途 |
| uvicorn[standard] | ASGI 服务器,用于运行 FastAPI 应用 |
| python-multipart | 表单数据和文件上传支持 |
| jinja2 | HTML 模板引擎 |
| python-jose[cryptography] | JWT 令牌支持 |
| passlib[bcrypt] | 密码哈希与加密 |
| python-dotenv | 环境变量管理 |
3.1.4 安装 Uvicorn
FastAPI 是一个 ASGI 框架,需要一个 ASGI 服务器来运行,最常用的是 Uvicorn
-
[standard]会安装 uvloop(高性能事件循环)和 httptools(高性能 HTTP 解析器),显著提升性能 -
ASGI(Asynchronous Server Gateway Interface)是 Python 异步 Web 服务器与应用程序之间的标准接口,是 WSGI 的异步版本。传统框架如 Flask 使用 WSGI(同步),而 FastAPI 使用 ASGI(异步),能够更高效地处理并发请求
bash
pip install "uvicorn[standard]"

3.2 FastAPI使用
使用FastAPI编写接口的完整流程:
-
导入FastAPI
-
创建FastAPI实例对象
-
创建路径操作函数,定义访问路径
-
运行FastAPI服务
-
fastapi dev "xxxx.py"
-
uvicorn xxxx:app--reload
-
在main函数中使用下面这种方式启动
- uvicorn.run(app, host="0.0.0.0", port=8000)
-
3.2.1 第一个 FastAPI 程序
上面的命令安装完成FastAPI后,创建一个main.py文件,在文件中添加如下3个接口代码
python
from fastapi import FastAPI
# 创建 FastAPI 应用实例
app = FastAPI()
# 定义根路径的 GET 请求
@app.get("/")
async def root():
return {"message": "Hello World"}
# 定义 /items/{item_id} 路径的 GET 请求
@app.get("/items/{item_id}")
async def get_item(item_id: int):
return {"item_id": item_id, "name": f"Item {item_id}"}
# 定义 /users/ 路径的 POST 请求
@app.post("/users/")
async def create_user(name: str, age: int):
return {"name": name, "age": age, "message": "User created successfully"}
3.2.2 启动服务
通过命令行定位到当前的这个main.py文件,然后执行下面的命令把服务运行起来
bash
uvicorn main:app --reload
看到下面的效果说明启动成功

启动参数说明:
-
main:app
- main 指文件名 main.py,app 指文件中创建的 FastAPI 实例变量名
-
--reload
- 开发模式,代码修改后自动重载服务器(仅用于开发环境)
3.2.3 接口效果验证
分别测试一下几个接口
1、第一个接口

2、第二个接口

3、第三个接口

3.2.4 接口文档
同时,服务启动之后,FastAPI 自动生成了交互式 API 文档:
访问交互式文档:
-
Swagger UI: High Performance Web Crawler API - Swagger UI

3.2.5 使用FastAPI CLI 启动服务
FastAPI 新版本提供了 fastapi 命令行工具,可以更方便地运行应用,需要先安装下面的依赖
bash
pip install "fastapi[standard]"

安装完成后,可以使用下面的命令启动服务
bash
# 开发模式(自动重载),适用于日常开发或者开发环境的服务启动
# 当你修改代码后,服务器会自动重启,让你能立即看到效果
fastapi dev (或者:fastapi dev main.py)
# 生产模式(不能自动重载),适用于线上环境服务启动
# 出于性能考虑,默认关闭了自动重载功能
fastapi run (或者:fastapi run main.py)
比如我启动开发模式下的服务

再次测试一下,仍然可以正常访问

补充:
-
无论是哪个命令,FastAPI CLI 在内部都是使用 Uvicorn 这个高性能的 ASGI 服务器来运行你的应用
-
fastapi dev会自动查找项目中的 FastAPI 应用并启动开发服务器,等同于uvicorn main:app --reload
3.2.6 使用uvicorn 启动
上面通过命令行的方式启动是不是有点不方便,还可以直接编写main函数,通过uvicorn 来启动
python
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
async def root():
return {"message": "Hello World"}
if __name__ == '__main__':
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)

四、FastAPI 接口请求参数使用
4.1 接口参数
4.1.1 接口参数说明
在实际开发中,为了响应页面的数据要求,同一段接口逻辑,需要根据参数不同返回不同的数据,比如在下面这个图中,根据不同的书籍ID查询不同的图书信息,ID就是动态传入的,接口也需要返回不同的书籍信息
-
参数就是客户端发送请求时附带的额外信息和指令
-
参数的作用是让同一个接口能根据不同的输入,返回不同的输出,实现动态交互

4.1.2 接口参数分类
参数可以分为下面3类

4.2 路径参数
路径参数是 URL 路径中的动态部分,使用花括号 {} 声明。FastAPI 会自动将路径参数传递给路径操作函数,并根据类型注解进行数据转换和校验。

使用 Python 格式化字符串的语法声明路径参数,下面这段代码展示了如何使用路径参数:
python
from fastapi import FastAPI
app = FastAPI()
# {item_id} 是路径参数
@app.get("/items/{item_id}")
async def read_item(item_id: int):
return {"item_id": item_id}
4.2.1 路径参数类型
除了 int,你还可以使用其他标准 Python 类型:
|-----------|-----------|---------------------------------------------|
| 类型 | 说明 | URL 示例 |
| str | 字符串(默认类型) | /items/foo |
| int | 整数 | /items/5 |
| float | 浮点数 | /items/5.5 |
| bool | 布尔值 | /items/true |
| uuid.UUID | UUID | /items/3fa85f64-5717-4562-b3fc-2c963f66afa6 |
4.2.2 路径顺序
当多个路由可能匹配同一个 URL 时,定义的顺序决定了匹配结果。FastAPI 按照路由定义的顺序依次匹配,第一个匹配的路由将被执行。如下代码:
python
from fastapi import FastAPI
app = FastAPI()
# 必须在 /users/{user_id} 之前定义
@app.get("/users/me")
async def read_user_me():
"""获取当前用户信息"""
return {"user_id": "the current user"}
@app.get("/users/{user_id}")
async def read_user(user_id: str):
"""根据 ID 获取用户信息"""
return {"user_id": user_id}
如果把 /users/me 放在 /users/{user_id} 之后,那么访问 /users/me 时,FastAPI 会认为 "me" 是 user_id 的值,从而匹配到错误的函数
- 固定路径的路由一定要放在动态路径参数的路由之前,否则动态参数会把固定路径的值"吞掉"
4.2.3 预设值的路径参数(Enum)
当你需要限制路径参数只能是几个固定值时,可以使用 Python 的 Enum 类型,如下代码:
python
from enum import Enum
from fastapi import FastAPI
# 创建枚举类,继承 str 和 Enum
class ModelName(str, Enum):
alis = "alis"
evy = "evy"
lenet = "lenet"
app = FastAPI()
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
# 可以与枚举成员比较
if model_name is ModelName.alis:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
启动服务器后测试一下接口

如果传入非预设值(如 /models/foobar),FastAPI 会返回校验错误,提示可选值为 alis、evy、lenet

枚举 类的要点:
|--------------------|---------------------------|
| 要点 | 说明 |
| 继承 str | 让 API 文档将值类型识别为字符串,确保正确渲染 |
| 继承 Enum | 创建枚举类型,限制可选值 |
| model_name.value | 获取枚举成员的实际值(如 "alexnet") |
4.2.4 包含路径的路径参数
当你需要路径参数本身包含路径(如文件路径)时,使用 Starlette 的路径转换器,参考下面的代码
python
from fastapi import FastAPI
app = FastAPI()
# :path 表示该参数可以匹配包含斜杠的路径
@app.get("/files/{file_path:path}")
async def read_file(file_path: str):
return {"file_path": file_path}

注意:
- 注意 URL 中 /files/ 和 /home/ 之间会出现双斜杠 //,这是正常的,因为路径参数以 / 开头
4.3 查询参数
查询参数是 URL 中 ? 之后、以 & 分隔的键值对。当函数参数不是路径参数也不是请求体时,FastAPI 会将其自动解释为查询参数。
4.3.1 基本用法
声明查询参数只需要在函数参数中添加类型注解和默认值,如下这段代码:
python
from fastapi import FastAPI
app = FastAPI()
# skip 和 limit 是查询参数,有默认值
fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]
@app.get("/items/")
async def read_item(skip: int = 0, limit: int = 10):
# 模拟分页查询
return fake_items_db[skip : skip + limit]
针对代码中的参数,有下面的访问形式
|--------------------------|---------|----------|------------------------|
| URL | skip 的值 | limit 的值 | 说明 |
| /items/ | 0 | 10 | 使用默认值 |
| /items/?skip=20 | 20 | 10 | skip 使用传入值,limit 使用默认值 |
| /items/skip=20&limit=5 | 20 | 5 | 两个参数都使用传入值 |
其他可选参数
-
将默认值设为
None即可声明可选的查询参数 -
在下面的接口中,这里
q: str | None = None表示q可以是字符串或None,默认值为None。
python
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: str, q: str | None = None):
# item_id 是路径参数(必填),q 是查询参数(可选)
if q:
return {"item_id": item_id, "q": q}
return {"item_id": item_id}
FastAPI 通过默认值
= None判断参数是否必填,而不是通过类型注解str | None。类型注解主要帮助编辑器提供更好的支持。
4.3.2 必选查询参数
不设置默认值的查询参数即为必选参数:
python
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: str, needy: str):
# needy 没有默认值,是必选查询参数
return {"item_id": item_id, "needy": needy}
在上面的代码中,如果接口参数中不传needy,调用将会报下面的错误

4.3.3 参数混合使用
混合使用必选、有默认值和可选参数,可以在同一个函数中混合使用不同类型的查询参数:
python
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(
item_id: str, # 路径参数(必填)
needy: str, # 必选查询参数
skip: int = 0, # 有默认值的查询参数
limit: int | None = None, # 可选查询参数
):
item = {"item_id": item_id, "needy": needy, "skip": skip}
if limit:
item.update({"limit": limit})
return item
4.4 查询参数校验
FastAPI 允许开发者为查询参数声明额外的校验规则和元数据,例如字符串长度限制、正则匹配等。通过 Query 和 Annotated,你可以在不改变函数逻辑的情况下增强参数校验。
4.4.1 参数基本校验
以下示例为查询参数 q 添加最大长度限制:
python
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
# 使用 Annotated + Query 添加校验
q: Annotated[str | None, Query(max_length=5)] = None,
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
访问接口时,当我输入的参数长度超过5的时候报下面的错误

参数说明
|------------------------------|--------------------------|
| 部分 | 说明 |
| Annotated[str | None, ...] | 类型注解,表示 q 可以是字符串或 None |
| Query(max_length=50) | 校验规则,q 的最大长度为 50 个字符 |
| =None | 默认值,使参数变为可选 |
补充:
FastAPI 推荐使用
Annotated方式声明校验,而非将Query作为默认值。因为Annotated方式下, 函数 的默认值就是真正的默认值,更符合 Python 的直觉,且编辑器和类型检查工具支持更好。
4.4.2 同时添加更多参数校验
可以同时添加多种校验规则:
python
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
# 同时限制最小长度、最大长度和正则表达式
q: Annotated[str | None, Query(min_length=3, max_length=50, pattern="^fixedquery$")] = None,
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
正则表达式 ^fixedquery$ 的含义:
-
^-- 必须以接下来的字符开头 -
fixedquery-- 值必须精确等于fixedquery -
$-- 到此结束,后面不能有其他字符
4.4.3 带默认值的校验
你可以为查询参数同时设置默认值和校验规则:
python
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
# 默认值为 "fixedquery",同时要求最小长度为 3
q: Annotated[str, Query(min_length=3)] = "fixedquery",
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
注意:
- 任何类型的默认值(包括非
None值)都会让参数变为可选。没有默认值也没有Query(default=...)的参数是必填的。
4.4.4 必填参数
使用 Query 时,如果不声明默认值,参数就是必填的:
python
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
# 没有 = None,所以 q 是必填参数
q: Annotated[str, Query(min_length=3)],
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
results.update({"q": q})
return results
有时你需要客户端必须传值,但值可以是 None:
python
from typing import Annotated
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(
# 客户端必须提供 q 参数,但值可以是 None
q: Annotated[str | None, Query(min_length=3)],
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
results.update({"q": q})
return results
4.5 路径参数值校验
与查询参数使用 Query 添加校验的方式相同,你可以使用 Path 为路径参数声明数值校验和元数据。
4.5.1 Path导入
从 fastapi 导入 Path,从 typing 导入 Annotated
- 路径参数总是必填的,因为它必须是 URL 路径的一部分。即使你为其声明了默认值,它仍然会作为必填参数处理
python
from typing import Annotated
from fastapi import FastAPI, Path
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
# 为路径参数添加元数据和校验
item_id: Annotated[int, Path(title="商品ID", description="要获取的商品ID", ge=1)],
):
return {"item_id": item_id}

4.5.2 Path 校验参数说明
Path 和 Query 都支持以下数值校验参数:
|------|------|--------------------------------|
| 参数 | 含义 | 英文来源 |
| gt | 大于 | g reater than |
| ge | 大于等于 | g reater than or equal |
| lt | 小于 | l ess than |
| le | 小于等于 | l ess than or equal |
4.5.3 数值组合校验
在下面的案例中,限定了输入参数的取值范围
python
from typing import Annotated
from fastapi import FastAPI, Path, Query
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
# item_id 必须 > 0 且 <= 1000
item_id: Annotated[int, Path(gt=0, le=1000)],
# 查询参数也可以用数值校验
size: Annotated[float, Query(gt=0, lt=10.5)] = 5.0,
):
return {"item_id": item_id, "size": size}
4.5.4 路径参数与查询参数混合使用
当你同时使用 Path 和 Query 时,使用 Annotated 可以避免参数顺序的问题:
python
from typing import Annotated
from fastapi import FastAPI, Path, Query
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
# 使用 Annotated 后,参数顺序无关紧要
item_id: Annotated[int, Path(title="商品ID", ge=1, le=1000)],
q: Annotated[str | None, Query(max_length=50)] = None,
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results

4.5.5 小结
路径参数数值校验的核心要点:
-
使用
Annotated+Path声明路径参数的校验规则 -
数值校验:
gt(大于)、ge(大于等于)、lt(小于)、le(小于等于) -
Path和Query共享相同的校验参数,包括字符串校验(min_length等)和元数据(title、description等) -
路径参数始终是必填的,无论是否声明默认值
4.6 请求体参数
4.6.1 什么是请求体参数
请求体是客户端发送给 API 的数据。当你需要从客户端接收 JSON 数据时,使用请求体来传递。FastAPI 使用 Pydantic 模型来声明请求体的结构,自动完成数据校验、转换和文档生成。

4.6.2 请求体与查询参数的区别
两者之间的主要区别如下
|--------|--------------------|------------|------------------|
| 数据传递方式 | 位置 | 适用场景 | HTTP 方法 |
| 路径参数 | URL 路径 /items/5 | 标识资源 | GET、PUT、DELETE 等 |
| 查询参数 | URL 中 ?key=value | 筛选、分页等可选参数 | 主要是 GET |
| 请求体 | 请求的 JSON 数据 | 提交复杂数据 | POST、PUT、PATCH |
发送数据应使用 POST(最常见)、PUT、DELETE 或 PATCH。虽然 FastAPI 技术上支持 GET 请求携带请求体,但这不符合 HTTP 规范,Swagger UI 也不会为 GET 请求显示请求体文档。
4.6.3 使用 Pydantic 模型声明请求体
导入 BaseModel,定义一个继承 BaseModel 的类,使用 Python 标准类型声明所有属性:
python
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
# 定义请求体数据模型
class Item(BaseModel):
name: str # 必填:商品名称
description: str | None = None # 可选:商品描述
price: float # 必填:商品价格
tax: float | None = None # 可选:税费
class User(BaseModel):
username: str
password: str
@app.post("/register")
async def create_item(user: User):
return user
运行服务,接口调用看下效果

4.6.4 请求体参数-类型注解Field
导入pydantic 的Field 函数

在导入的模块中增加 Field,如下代码
python
from fastapi import FastAPI
from pydantic import BaseModel,Field
app = FastAPI()
# 定义请求体数据模型
class Item(BaseModel):
name: str # 必填:商品名称
description: str | None = None # 可选:商品描述
price: float # 必填:商品价格
tax: float | None = None # 可选:税费
class User(BaseModel):
username: str=Field(default="张三",min_length=2,max_length=10,description="用户名长度必须是2到10之间")
password: str=Field(min_length=5,max_length=20)
@app.post("/register")
async def create_item(user: User):
return user
运行下看效果,如果不符合参数要求,将会报下面的额错误

4.6.5 请求体 + 路径参数 + 查询参数混合
可以将三者同时使用,如下代码
python
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
# 同时使用路径参数、查询参数和请求体
@app.put("/items/{item_id}")
async def update_item(item_id: int, item: Item, q: str | None = None):
result = {"item_id": item_id, **item.model_dump()}
if q:
result.update({"q": q})
return result
FastAPI 的完整参数识别规则:
|-------------------------------|----------|
| 识别条件 | 参数来源 |
| 参数名在路径的 {} 中声明 | 路径参数 |
| 参数是单一类型(int、str、bool 等) | 查询参数 |
| 参数类型是 Pydantic 模型 | 请求体 |
4.6.6 小结
请求体的核心要点:
-
使用 Pydantic 的
BaseModel定义请求体结构 -
有默认值的字段可选,没有默认值的字段必填
-
请求体可以与路径参数和查询参数同时使用
-
FastAPI 自动完成数据校验、类型转换和文档生成
-
Pydantic v2 使用
model_dump()进行序列化
五、写在最后
本文通过案例操作演示了FastAPI从环境搭建到查询参数的使用,希望对看到的同学有用哦,本文到此结束,感谢观看。