Skip to main content
今日目标:API 的安全性始于”入口安检”。今天我们将深入学习 Pydantic,它是 FastAPI 的心脏。学会定义数据模型,让 API 能够自动拒绝那些缺字段、格式错误或类型不对的”脏数据”。今天不只是写代码,而是要彻底理解 “为什么需要数据验证”“Pydantic 如何自动验证数据” 以及 “如何设计合理的 Schema”

学习内容 (30 mins)

在开始写代码前,先搞懂这些核心概念,否则后面的代码你会看得云里雾里。
什么是 Pydantic?Pydantic 是一个数据验证库,使用 Python 类型提示来验证数据。它是 FastAPI 的核心依赖,负责验证请求和响应数据。为什么需要数据验证?
  • 安全性:防止恶意数据注入
  • 数据完整性:确保数据格式正确
  • 开发效率:自动验证,减少手动检查代码
  • 文档生成:自动生成 API 文档
传统方式 vs Pydantic传统方式(Flask/Django)
Pydantic 方式(FastAPI)
Pydantic 的优势
  • 声明式:定义模型即可,无需写验证逻辑
  • 自动转换:自动将字符串转换为整数、日期等
  • 详细错误:提供详细的验证错误信息
  • 类型安全:基于 Python 类型提示,IDE 支持好
Schema(模式)Schema 是数据的”说明书”,定义了数据的结构和验证规则。
  • 定义方式:继承 pydantic.BaseModel
  • 字段类型:使用 Python 类型提示(str、int、float、bool 等)
  • 验证规则:使用 Field() 定义更细的规则
Field(字段)Field() 用于给字段添加验证规则和元数据。
  • ...:表示必填字段(Ellipsis)
  • min_length:字符串最小长度
  • max_length:字符串最大长度
  • gt:大于(greater than)
  • lt:小于(less than)
  • ge:大于等于(greater or equal)
  • le:小于等于(less or equal)
  • description:字段描述(会显示在 Swagger 文档中)
请求模型 vs 响应模型
  • 请求模型(Request Model):定义前端发送的数据结构
    • 通常包含所有字段,包括密码等敏感信息
    • 示例:UserCreate(创建用户时的数据)
  • 响应模型(Response Model):定义返回给前端的数据结构
    • 通常不包含敏感信息(如密码)
    • 使用 response_model=UserResponse 自动过滤字段
    • 示例:UserResponse(返回用户信息,不含密码)
EmailStr 和特殊类型Pydantic 提供了很多特殊类型,用于常见的数据验证:
  • EmailStr:自动验证邮箱格式(需要安装 email-validator
  • IPvAnyAddress:验证 IP 地址格式
  • HttpUrl:验证 URL 格式
  • datetime:自动解析日期时间字符串

代码任务 (90 mins)

1

环境准备

确保虚拟环境已激活,并安装必要的包:
2

任务 A:定义严格的用户模型

新建 schemas.py 文件,定义数据模型。任务分解
  1. 定义请求模型(UserCreate)- 用于创建用户
  2. 定义响应模型(UserResponse)- 用于返回用户信息
  3. 使用 Field 添加验证规则
代码解释
  • Field(...)... 表示必填字段
  • Field(None, ...)None 是默认值,表示可选字段
  • min_length:字符串最小长度验证
  • gtlt:数值范围验证
  • EmailStr:自动验证邮箱格式
  • Optional[int]:可选字段,类型为 int 或 None
验证步骤
  1. 检查文件语法是否正确
  2. 尝试导入:python -c "from schemas import UserCreate, UserResponse; print('OK')"
3

任务 B:集成到 API 路由

修改 16_main.py,使用刚才定义的模型。
代码解释
  • user: UserCreate:FastAPI 自动验证请求体
  • response_model=UserResponse:自动过滤响应中的字段
  • status_code=201:创建成功返回 201(Created)
  • HTTPException:抛出 HTTP 异常,FastAPI 自动转换为错误响应
运行脚本
验证步骤
  1. 访问 http://localhost:8000/docs 打开 Swagger UI
  2. 测试创建用户接口:
    • 点击 POST /users/
    • 点击 “Try it out”
    • 输入正确的数据,执行,应该返回 201
    • 输入错误的数据(如密码太短),执行,应该返回 422 错误
  3. 验证响应模型:
    • 创建用户后,查看返回的数据
    • 确认返回的数据中不包含 password 字段
常见错误
  • 422 Validation Error - 请求数据不符合 Schema 定义,检查字段类型和验证规则
  • ImportError: cannot import name 'EmailStr' - 未安装 email-validator,执行 pip install email-validator
  • FieldInfo(...) 错误 - Field 使用错误,检查语法
4

任务 C:测试数据验证

使用 Swagger UI 测试各种错误情况,观察 FastAPI 如何自动验证。测试用例
  1. 密码太短
    • 预期:422 Error,错误信息:ensure this value has at least 8 characters
  2. 邮箱格式错误
    • 预期:422 Error,错误信息:value is not a valid email address
  3. 年龄越界
    • 预期:422 Error,错误信息:ensure this value is less than 120
  4. 缺少必填字段
    • 预期:422 Error,错误信息:field required(password 和 email)
  5. 正确的数据
    • 预期:201 Created,返回用户信息(不含密码)
这就是声明式编程的魅力:你只负责立规矩,FastAPI 负责当警察。

拓展任务 (30 mins)

挑战 1:自定义验证器

任务:使用 @validator 装饰器添加自定义验证逻辑。例如:验证用户名不能包含特殊字符。提示

挑战 2:嵌套模型

任务:创建一个包含嵌套模型的 Schema。例如:用户模型包含地址信息(地址也是一个模型)。提示

今日产出物

  • schemas.py - Pydantic 数据模型定义
  • 16_main.py - 使用 Pydantic 的 FastAPI 应用

参考代码

查看参考代码

在 GitHub 查看完整的示例代码

在线运行

使用在线编辑器测试代码

实际应用场景

Pydantic 在 API 开发中的应用

  • 请求验证:自动验证前端发送的数据格式
  • 响应过滤:自动过滤敏感字段(如密码)
  • 类型转换:自动将字符串转换为整数、日期等
  • 文档生成:自动生成 API 文档,显示字段说明
  • 数据序列化:自动将 Python 对象转换为 JSON

Schema 设计最佳实践

  • 分离请求和响应模型:请求模型包含所有字段,响应模型排除敏感字段
  • 使用 Field 添加规则:利用 min_length、gt、lt 等规则增强验证
  • 提供默认值:为可选字段设置合理的默认值
  • 添加描述:使用 description 参数,便于生成文档
  • 使用特殊类型:EmailStr、IPvAnyAddress 等,减少手动验证代码
与 Day 17 的关联:今天学习的 Pydantic 数据验证,明天会学习依赖注入和中间件,将验证逻辑封装成可复用的依赖函数。

上一天: 快速入门

Day 15 | FastAPI 快速入门

下一天: 依赖注入

Day 17 | 依赖注入与中间件