Pydantic 是目前 Python 中最流行的数据验证和设置管理库(FastAPI 的核心基石)。目前主流版本是 V2(由 Rust 重写,性能极高)。

1.BaseModel

from pydantic import BaseModel
from typing import List, Optional

class User(BaseModel):
	id: int
	name: str
	signup_ts: Optional[str] = None # 可选字段,默认为None
	friends: List[int] = []

user_data = {
	"id": 123,
	"name": "测试用户",
	"signup_ts": "2024-01-01 10:00",
	"friends": [1, 2, 3]
}

user = User(**user_data)
print(user.id)

# 错误数据会抛出 ValidationError
try:
	User(id = "NaN", name = "测试")
except Exception as e:
	print(e)

值得注意的是,Pydantic 不是简单的类型检查,它是数据解析器。如果输入是 float 1.0 但字段定义是 int,它会尝试将其转为 1;如果无法转换,才会报错。

2.Field

当仅用类型提示无法满足需求时(例如需要限制数值范围、字符串长度、默认值工厂),我们使用 Field 函数。

常用 Field 参数:

参数 含义 示例
default 默认值 default=0
default_factory 默认值生成函数 default_factory=list
alias 别名(输入数据时的键名) alias="user_name"
gt / ge 大于 / 大于等于 gt=0
lt / le 小于 / 小于等于 le=100
min_length / max_length 字符串/列表长度限制 max_length=10
pattern 正则表达式验证 pattern=r'^\d+$'
例如:
from pydantic import BaseModel, Field
from uuid import uuid4, UUID

class Product(BaseModel):
	sku: UUID = Field(default_factory = uuid64)
	price: float = Field(gt = 0, le = 1000, description = "商品价格")
	name: str = Field(min_length = 2, max_length = 50, pattern = r'^[a-zA-Z0-9_]+$')
	
data = {"price": 99.9, "name": "Phone_15", "is_active": False} 

p = Product(**data) 
print(p.active)

3.Validator

这是 Pydantic 的灵魂。Field函数只能拒绝错误的值,但不能修改(例如,有时候需要将数据清洗为标准的格式),而Validator的装饰器可以更灵活的保证数据的合法性。在 V2 中,我们主要使用 @field_validator (针对单个字段) 和 @model_validator (针对整个模型)。

1️⃣.单字段校验(@field_validator

这个装饰器用于检查某个字段(单个的字段)的值是否符合特定的业务规则。

例如:

from pydantic import BaseModel, Field, field_validator

class Student(BaseModel):
	name: str
	score: int
	
	@field_validator("score")
	@classmethod
	def check_score(cls, v :int) -> int:
		if v < 0 or v > 100:
			raise ValueError("分数必须在0-100之间")
		return v
	
	@field_validator("name")
	@classmethod
	def name_must_be_title(cls, v :str) -> str:
		if not v.istitle():
			return v.title()
		return v

因为field_validator生效的时期位于调用类的构造函数之前,此时没有self对象。所以我们必须将这个装饰器绑定到类方法上(即需要使用@classmethod修饰)。

2️⃣.多字段依赖校验(@model_validator

当验证逻辑需要同时访问多个字段时,我们就需要用到@model_validator。和@field_validator相比,不只是访问的字段不止一个,@model_validator提供了两种方法:

  • mode = "before":和单字段验证一样,校验发生在类生成前,此时必须用@classmethod
  • mode = "after":此时校验发生在类生成后,也就是对具体的实例进行校验的,此时无需绑定@classmethod

例如:

from pydantic import BaseModel, model_validator
from typing import Any

class RegisterRequest(BaseModel)
	password: str
	confirm_password: str
	
	@model_validator(mode = "after")
	def check_passwords_match(self) -> "RegisterRequest" :
		if self.password != self.confirm_password:
			raise ValueError("两次输入的密码不一致!")
		return self

4.序列化导出

在V2版本中,Pydantic提供了非常方便的序列化方法:

  • model_dump():转为Python字典。
  • model_dump_json():转为JSON字符串。

例如:

class Config(BaseModel):
	host: str = "localhost"
	port: int = 8080

conf = Config()

# 1.转字典
print(conf.model_dump())
# 输出: {'host': 'localhost', 'port': 8080}

# 2.转字典,同时排除某些字段
print(conf.model)dump(exclude = {"host"})
# 输出: {'port': 8080}

# 3. 转 JSON 字符串 
print(conf.model_dump_json()) 
# 输出: '{"host":"localhost","port":8080}'

5.配置文件管理:pydantic-settings

在工程实践中,我们通常用 Pydantic 来管理环境变量。需要先安装: pip install pydantic-settings
这是一个非常强大方便的功能,它可以读取.env文件或系统设置的环境变量。

例如:

from pydantic import BaseModel
from pydantic_settings import BaseSettings, SettingsConfigDict

class AppSettings(BaseSettings):
	app_name: str = "My App"
	db_url: str
	api_key: str
	
	# 读取.env文件
	model_config = SettingsConfigDict(env_file = ".env", env_file_encoding = "utf-8")
	
# 这样,在我们实例化AppSettings这个类的时候,Pydantic会自动去系统环境变量里找 名为(pydantic不区分大小写)'APP_NAME', 'DB_URL','API_KEY'的变量的值。
# 另外,我们还让他读取.env文件,所以他也会去相应的文件里查找。