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":和单字段验证一样,校验发生在类生成前,此时必须用@classmethodmode = "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文件,所以他也会去相应的文件里查找。
评论