【Python基础】FastAPI 从入门到项目实战操作详解

目录

一、前言

[二、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 框架中脱颖而出,主要得益于以下特点:

  1. 高性能

    1. 基于 Starlette 和 Pydantic,性能与 NodeJS 和 Go 相当,是最快的 Python 框架之一
  2. 快速开发

    1. 开发速度提升约 200%-300%,标准类型声明即可完成数据校验和文档生成
  3. 减少错误

    1. 减少约 40% 的人为错误,类型系统自动捕获常见问题
  4. 自动生成文档

    1. 自动生成交互式 API 文档(Swagger UI 和 ReDoc),无需手动维护
  5. 类型安全

    1. 基于标准 Python 类型提示,编辑器提供全面的自动补全和错误检查
  6. 异步支持

    1. 原生支持 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 文档:

访问交互式文档:

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 允许开发者为查询参数声明额外的校验规则和元数据,例如字符串长度限制、正则匹配等。通过 QueryAnnotated,你可以在不改变函数逻辑的情况下增强参数校验。

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 校验参数说明

PathQuery 都支持以下数值校验参数:

|------|------|--------------------------------|
| 参数 | 含义 | 英文来源 |
| 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 路径参数与查询参数混合使用

当你同时使用 PathQuery 时,使用 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(小于等于)

  • PathQuery 共享相同的校验参数,包括字符串校验(min_length 等)和元数据(titledescription 等)

  • 路径参数始终是必填的,无论是否声明默认值

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 的完整参数识别规则:

|-------------------------------|----------|
| 识别条件 | 参数来源 |
| 参数名在路径的 {} 中声明 | 路径参数 |
| 参数是单一类型(intstrbool 等) | 查询参数 |
| 参数类型是 Pydantic 模型 | 请求体 |

4.6.6 小结

请求体的核心要点:

  • 使用 Pydantic 的 BaseModel 定义请求体结构

  • 有默认值的字段可选,没有默认值的字段必填

  • 请求体可以与路径参数和查询参数同时使用

  • FastAPI 自动完成数据校验、类型转换和文档生成

  • Pydantic v2 使用 model_dump() 进行序列化

五、写在最后

本文通过案例操作演示了FastAPI从环境搭建到查询参数的使用,希望对看到的同学有用哦,本文到此结束,感谢观看。

相关推荐
卷无止境1 天前
当FastAPI遇上机器学习,一个脚手架工具能省下多少工夫
后端·python·fastapi
练习两年半的攻城狮1 天前
【RAG实战】知识库 BGE-M3 稀疏向量混合检索方案
python·fastapi·llamaindex
哒咩哒咩1291 天前
Agent 智能体开发全攻略:从 ReAct 到企业级架构
python·langchain·fastapi
创新技术阁2 天前
FastapiAdmin 前后端启动全流程详解
前端·后端·fastapi
典典分享指南2 天前
飞书 + 企业微信 + 微信文档多端协同实践指南
汇编·flask·intellij-idea·fastapi
鲨鱼辣钊2 天前
FastAPI筑基_Day15_Alembic数据库迁移实战
数据库·elasticsearch·fastapi
Broccoli523026652 天前
FastAPI 中 Pydantic 模型与 SQLAlchemy ORM 模型的分工与转换规范
fastapi
云和数据.ChenGuang2 天前
git revert回退问题
java·服务器·人工智能·git·fastapi·强化学习
卷无止境2 天前
FastAPI生产环境密钥管理全解析,从一个.env文件说起
后端·python·fastapi