You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何自定义Pydantic的友好型验证错误提示信息?

优化Pydantic自定义验证错误消息的方案

不用写大量样板验证器,有几个更高效的解决思路:

1. 利用字段约束参数+自定义错误消息

Pydantic的Field或StringConstraints支持直接配置长度、格式等约束,同时通过error_messages自定义错误文本,完全替代手写验证器的重复逻辑。

示例代码:

from pydantic import BaseModel, EmailStr, Field, StringConstraints
from typing import Annotated

# 复用的密码类型,封装约束和错误消息
PasswordStr = Annotated[
    str,
    StringConstraints(
        min_length=8,
        max_length=32,
        regex=r"^(?=.*[A-Z])(?=.*\d).+$",
        error_messages={
            "min_length": "密码长度不能少于8位",
            "max_length": "密码长度不能超过32位",
            "regex": "密码必须包含至少一个大写字母和一个数字"
        }
    )
]

class RegisterModel(BaseModel):
    email: EmailStr = Field(..., error_messages={"value_error": "请输入有效的邮箱地址"})
    password: PasswordStr

这样既保留了Pydantic自动验证的便捷性,又自定义了友好的错误消息,还能把PasswordStr类型复用在其他需要密码验证的模型里。

2. 抽离复用自定义验证器

如果有复杂到无法用内置约束覆盖的逻辑,可以把验证逻辑封装成单独的可复用函数,避免每个模型重复写验证器代码。

示例代码:

from pydantic import BaseModel, EmailStr, field_validator, ValidationInfo
import re

# 抽离通用密码验证逻辑
def validate_password(value: str, info: ValidationInfo) -> str:
    if not isinstance(value, str):
        raise ValueError("密码必须是字符串类型")
    if len(value) < 8:
        raise ValueError("密码长度不能少于8位")
    if len(value) > 32:
        raise ValueError("密码长度不能超过32位")
    if not re.search(r"[A-Z]", value):
        raise ValueError("密码必须包含至少一个大写字母")
    if not re.search(r"[0-9]", value):
        raise ValueError("密码必须包含至少一个数字")
    return value

class RegisterModel(BaseModel):
    email: EmailStr
    password: str

    @field_validator("password", mode="before")
    def _validate_password(cls, value, info):
        return validate_password(value, info)

# 其他模型直接复用验证函数
class LoginModel(BaseModel):
    password: str

    @field_validator("password", mode="before")
    def _validate_password(cls, value, info):
        return validate_password(value, info)

3. 多语言消息适配

如果需要给不同语言的用户返回对应消息,可以用pydantic-i18n库管理多语言文本,无需硬编码多套消息。

步骤示例:

  1. 安装依赖:pip install pydantic-i18n
  2. 创建多语言配置文件(比如locales/zh.json、locales/en.json)
    // locales/zh.json
    {
        "value_error.email": "请输入有效的邮箱地址",
        "value_error.any_str.min_length": "密码长度不能少于{limit_value}位",
        "value_error.any_str.max_length": "密码长度不能超过{limit_value}位",
        "value_error.str.regex": "密码必须包含至少一个大写字母和一个数字"
    }
    
  3. 绑定翻译器到模型:
    from pydantic_i18n import PydanticI18n, Config
    from pydantic import BaseModel, EmailStr, StringConstraints
    from typing import Annotated
    
    config = Config(locales_dir="locales")
    i18n = PydanticI18n(config)
    
    PasswordStr = Annotated[
        str,
        StringConstraints(min_length=8, max_length=32, regex=r"^(?=.*[A-Z])(?=.*\d).+$")
    ]
    
    class RegisterModel(BaseModel):
        email: EmailStr
        password: PasswordStr
    
        class Config:
            @classmethod
            def json_schema_extra(cls, schema, model):
                # 根据用户请求的语言动态切换,这里示例用中文
                schema["error_messages"] = i18n.translate("zh")
    

内容的提问来源于stack exchange,提问作者Clyde

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 16:45:03