title: Pydantic字段级校验:解锁@validator的12种应用

date: 2025/3/23

updated: 2025/3/23

author: cmdragon

excerpt:

Pydantic校验系统支持通过pre验证器实现原始数据预处理,在类型转换前完成字符清洗等操作。格式验证涵盖正则表达式匹配与枚举值约束,确保护照编号等字段符合规范。动态校验机制处理跨字段依赖关系及环境感知验证,根据运行时条件调整校验规则。安全校验模块防御SQL注入与XSS攻击,采用字符过滤和HTML转义策略。高级转换功能实现地址标准化、敏感信息加密等数据处理,企业级实践包含分布式ID验证与金融精度控制。校验错误处理需关注类型一致性及验证顺序,遵循"早失败"原则构建模块化校验规则库,推荐使用参数化查询等最佳安全实践。

categories:

  • 后端开发
  • FastAPI

tags:

  • Pydantic字段校验
  • @validator高级应用
  • 数据验证模式
  • 防御式编程
  • 校验器组合
  • 动态依赖验证
  • 企业级数据清洗

扫描二维码关注或者微信搜一搜:编程智域 前端至全栈交流与成长

探索数千个预构建的 AI 应用,开启你的下一个伟大创意


第一章:基础校验模式

1.1 类型强制转换

from pydantic import BaseModel, validator

class CurrencyConverter(BaseModel):
amount: str @validator("amount", pre=True)
def string_to_float(cls, v):
return float(v.strip("$")) # 自动转换 "$100.5" → 100.5
print(CurrencyConverter(amount="$100.5").amount)

pre验证器特性

  • 在类型转换前执行
  • 支持原始数据清洗
  • 可处理非结构化输入

第二章:格式验证

2.1 正则表达式验证

import re

class IdentityForm(BaseModel):
passport: str @validator("passport")
def validate_passport(cls, v):
if not re.match(r"^[A-PR-WY][1-9]\d\s?\d{4}[A-Z]$", v):
raise ValueError("护照号码格式错误")
return v.upper().replace(" ", "")

2.2 枚举值约束

from enum import Enum

class Department(Enum):
HR = 1
IT = 2 class Employee(BaseModel):
dept: int @validator("dept")
def check_department(cls, v):
return Department(v).name # 自动转换数字为枚举名称

第三章:动态校验

3.1 跨字段依赖验证

class OrderForm(BaseModel):
product_type: str
weight: float @validator("weight")
def check_weight(cls, v, values):
if values.get("product_type") == "fragile" and v > 10:
raise ValueError("易碎品不得超过10kg")
return v

3.2 环境感知校验

import os

class EnvAwareValidator(BaseModel):
api_key: str @validator("api_key")
def check_key_format(cls, v):
env = os.getenv("APP_ENV", "dev")
if env == "prod" and len(v) < 32:
raise ValueError("生产环境密钥强度不足")
return v

第四章:安全校验

4.1 SQL注入防御

class QuerySafe(BaseModel):
search_term: str @validator("search_term")
def sanitize_input(cls, v):
forbidden = ["'", ";", "--", "/*"]
if any(c in v for c in forbidden):
raise ValueError("检测到危险字符")
return v.replace("%", "\\%")

4.2 XSS攻击过滤

from html import escape

class CommentForm(BaseModel):
content: str @validator("content")
def sanitize_html(cls, v):
return escape(v).replace("\n", "<br>")

第五章:高级转换

5.1 数据归一化

class AddressNormalizer(BaseModel):
street: str @validator("street")
def standardize_address(cls, v):
replacements = {
"St.": "Street",
"Ave": "Avenue"
}
for k, v in replacements.items():
v = v.replace(k, v)
return v.title()

5.2 加密字段处理

from cryptography.fernet import Fernet

class SecureData(BaseModel):
secret: str @validator("secret")
def encrypt_value(cls, v):
key = Fernet.generate_key()
return Fernet(key).encrypt(v.encode())

第六章:企业级实践

6.1 分布式ID验证

import snowflake

class SnowflakeValidator(BaseModel):
object_id: str @validator("object_id")
def validate_snowflake(cls, v):
try:
snowflake.deconstruct(v)
return v
except Exception:
raise ValueError("非法分布式ID格式")

6.2 金融精度控制

from decimal import Decimal, ROUND_HALF_UP

class FinancialModel(BaseModel):
amount: float @validator("amount")
def monetary_precision(cls, v):
return Decimal(str(v)).quantize(
Decimal("0.00"),
rounding=ROUND_HALF_UP
)

课后Quiz

Q1:pre验证器的执行时机是?

A) 类型转换后

B) 类型转换前

C) 最终验证阶段

Q2:防御SQL注入的最佳方法是?

  1. 字符串替换
  2. 参数化查询
  3. 正则过滤

Q3:处理多字段依赖应使用?

  • root_validator
  • 多个字段级校验器
  • 自定义__init__方法

错误解决方案速查表

错误信息 原因分析 解决方案
ValidationError: value is not a valid integer 类型转换前未清洗数据 添加pre=True验证器
ValueError: 检测到危险字符 SQL注入防御生效 使用参数化查询替代直接拼接
AssertionError: 校验顺序错误 依赖字段未优先验证 调整字段定义顺序
TypeError: 校验器返回类型错误 验证器返回值与声明类型不符 检查验证器逻辑

架构原则:字段校验应遵循"早失败"原则,在数据入口处完成所有验证。建议建立企业级校验规则库,通过装饰器模式实现校验逻辑的模块化管理。

余下文章内容请点击跳转至 个人博客页面 或者 扫码关注或者微信搜一搜:编程智域 前端至全栈交流与成长,阅读完整的文章:

往期文章归档:

Pydantic字段级校验:解锁@validator的12种应用的更多相关文章

  1. ETL应用:使用shell实现文件级校验的方法

    BI应用中,对接口规范性约束很重要,接口文件提供需要配套提供该文件的校验文件,校验文件格式如下: 序号 信息内容 数据类型及长度 说明 1 接口数据文件名称 CHAR(50) 2 文件的大小(字节数) ...

  2. SQL 建立多个字段唯一性校验

    由于在做压力测试,同一时间占用的问题. 两个用户同时下同一时间的订单,需要增加校验,第一个能保存的用户保存,第二个就不能让保存了. 问题是通过代码,怎么都做不到毫秒级校验,所以解决办法就只能是通过数据 ...

  3. Vue 两个字段联合校验典型例子--修改密码

    1.前言   本文是前文<Vue Element-ui表单校验规则,你掌握了哪些?>针对多字段联合校验的典型应用.   在修改密码时,一般需要确认两次密码一致,涉及2个属性字段.类似的涉及 ...

  4. Java-Runoob-高级教程-实例-方法:12. Java 实例 – Enum(枚举)构造函数及方法的使用-um

    ylbtech-Java-Runoob-高级教程-实例-方法:12. Java 实例 – Enum(枚举)构造函数及方法的使用 1.返回顶部 1. Java 实例 - Enum(枚举)构造函数及方法的 ...

  5. Java-Runoob-高级教程-实例-数组:12. Java 实例 – 数组差集

    ylbtech-Java-Runoob-高级教程-实例-数组:12. Java 实例 – 数组差集 1.返回顶部 1. Java 实例 - 数组差集  Java 实例 以下实例演示了如何使用 remo ...

  6. Java-Runoob-高级教程-实例-字符串:12. Java 实例 - 字符串优化

    ylbtech-Java-Runoob-高级教程-实例-字符串:12. Java 实例 - 字符串优化 1.返回顶部 1. Java 实例 - 字符串优化  Java 实例 以下实例演示了通过 Str ...

  7. Oracle 11g对依赖的推断达到字段级

    在Oracle 10g下,推断依赖性仅仅达到了对象级.也就是说存储过程訪问的对象一旦发生了变化.那么Oracle就会将存储过程置为INVALID状态.所以在为表做了DDL操作后.须要把存储过程又一次进 ...

  8. SNF快速开发平台2019-权限管理模型-记录级-字段级权限实践

    1.1.1  字段级权限 字段级权限适用于对不同人的能否查看或录入不同表不同字段的权限控制. 是否启用字段级权限配置 不启用字段级权限后,[用户权限管理]程序[字段级权限]按钮会隐藏,导致无法给管理其 ...

  9. MongoDB 4.2新特性:分布式事务、字段级加密、通配符索引、物化视图

    MongoDB 4.2已经发布,我们来看看它增加了哪些新特性?分布式事务?数据库加密?通配符索引? 在2019年MongoDB World大会上,CTO Eliot Horowitz介绍了MongoD ...

  10. Oval框架如何校验枚举类型的一种思路

    前言: Oval校验框架被广泛集成于各类接口参数校验中, 其方便的注解语法, 易读性和扩展性. 几乎成了java后端服务代码的标配. 有人会很疑惑, 都已经是枚举类型了, 还需要校验吗? 其实这边更确 ...

随机推荐

  1. 如何使用vs将现有的项目或者文件夹(尤其是多层目录的)添加到项目中

    在Visual Studio中将现有的项目或者文件夹(尤其是多层目录的)添加到项目解决方案中,步骤如下: 1.将现有项目或文件夹拷贝到指定目录下: 2.解决方案右上有个显示所有文件的按钮,如下图所示: ...

  2. Bogus:.NET的假数据生成利器

    我们在项目开发中,为了保证系统功能完整.准确性,我们都需要模拟真实数据进行测试. 今天推荐一个开源库,方便我们制造假数据测试. 01 项目简介 Bogus 是一个开源的 .NET 库,它提供了一个强大 ...

  3. MCU命令

    三D打印常用MCU命令 allocate_oids count=42 分配 42 个 OIDs,后续用于标识和管理不同的设备或组件 config_spi oid=0 pin=PD7 cs_active ...

  4. 认识Token和Cookie

    认识Token和Cookie 1.token和cookie有什么区别? ​ 1.1 存储位置及方式:Cookie是浏览器用来存储本地信息的文件,有一定的存储限制,而Token是由服务器按一定算法生成的 ...

  5. Java验证邮箱是否有用的实现与解析

    在现代互联网应用中,邮箱验证是一个常见的需求.通过邮箱验证,开发者可以确保用户提供的邮箱地址是有效的,从而在后续的操作中,如密码重置.通知发送等,依赖这些有效的邮箱地址.本文将详细介绍如何使用Java ...

  6. CDS标准视图:维护通知活动信息 I_MaintNotificationActyData

    视图名称:维护通知活动信息 I_MaintNotificationActyData 视图类型:基础 视图代码: 点击查看代码 @AbapCatalog.sqlViewName: 'INOTIFACTY ...

  7. .NET Core GC标记阶段(mark_phase)底层原理浅谈

    简介 C# 采用基于代的回收机制,并使用了更复杂的 链式跟踪算法 来识别对象是否为垃圾. GC触发的原因 截至到.NET 8,GC触发的原因有18种 enum gc_reason { reason_a ...

  8. weixueyuan-Nginx在Kubernetes10

    https://www.weixueyuan.net/nginx/kubernetes/ Kubernetes(k8s)分布式容器管理系统简述 Kubernetes 是分布式容器管理系统,它提供了对容 ...

  9. 一个SQL就让内存耗光了

    一个SQL内存为什么就没了呢 最近遇到一个故障,研发新上线一个功能,成功把主机内存耗光,导致实例重启.复现一个SQL如何把数据库的内存耗光. 实验环境 Oracle Database 19c(故障发生 ...

  10. 使用XManager远程连接服务器的时候使用Qt键盘会错位偏移

    问题 最近使用XManager访问服务器的xfce桌面,在使用Qt查看代码的时候发现键盘会错位 如下图,我输入application,最终显示这个 这样子就根本无法进行开发了 然后在网上找,发现有人出 ...