如何在Pydantic 2.0中实现EmailStr与ConstrainedStr的组合验证?
Pydantic 2.0 实现带标准化处理的邮箱字段验证
方案1:使用Annotated结合StringConstraints与EmailStr
Pydantic 2.0中,原ConstrainedStr被替换为StringConstraints,可直接通过Annotated将字符串约束与EmailStr验证逻辑组合,实现自动去空格、转小写+邮箱格式验证的需求:
from pydantic import BaseModel, EmailStr, StringConstraints, Annotated # 定义带标准化约束的邮箱字段 EmailApiField = Annotated[ EmailStr, StringConstraints(to_lower=True, strip_whitespace=True) ] # 用于请求模型 class LoginReq(BaseModel): email: EmailApiField
该方式会先对输入字符串执行去空格、转小写的标准化处理,再验证是否为合法邮箱格式,逻辑顺序与你原代码一致。
方案2:自定义验证函数+Annotated
如果需要更灵活的标准化逻辑,可手动编写处理函数,通过BeforeValidator指定在邮箱验证前执行:
from pydantic import BaseModel, EmailStr, BeforeValidator from typing import Annotated def normalize_email(input_str: str) -> str: return input_str.strip().lower() EmailApiField = Annotated[ EmailStr, BeforeValidator(normalize_email) ] class LoginReq(BaseModel): email: EmailApiField
方案3:自定义字段类型(贴近原Pydantic 1.x写法)
若习惯用自定义类的方式实现,可通过扩展EmailStr并实现核心验证规则来完成:
from pydantic import EmailStr, GetJsonSchemaHandler, StringConstraints from pydantic_core import core_schema from typing import Any from pydantic import BaseModel class EmailApiField(EmailStr): @classmethod def __get_pydantic_core_schema__(cls, source_type: Any, handler: GetJsonSchemaHandler) -> core_schema.CoreSchema: # 获取EmailStr的核心验证规则 email_schema = handler(EmailStr) # 获取字符串约束的处理逻辑(去空格、转小写) constraint_schema = StringConstraints(to_lower=True, strip_whitespace=True).__get_pydantic_core_schema__(str, handler) # 组合规则:先执行标准化处理,再验证邮箱格式 return core_schema.no_info_wrap_validator_function( constraint_schema['function'], email_schema, ) class LoginReq(BaseModel): email: EmailApiField
原写法失效原因
Pydantic 2.0中的constr是类型工厂函数,返回的是带约束的字符串类型,而非可直接用于BeforeValidator的处理函数。BeforeValidator要求接收一个可调用的处理逻辑,而非类型,因此原写法会报错。
内容的提问来源于stack exchange,提问作者Artur Stępniak
相关产品推荐
相关产品推荐

