调用返回带自定义验证器的Pydantic模型的Python函数时遇重复验证器错误
解决Pydantic动态创建模型时的重复验证器错误
错误原因
每次调用create_model生成内部CustomModel时,验证器函数validate_name的限定名称(__qualname__)完全相同(都是create_model.<locals>.CustomModel.validate_name)。Pydantic通过函数标识跟踪已注册的验证器,因此会判定为重复注册,抛出错误。
解决方法
方法一:给验证器设置唯一名称
通过动态修改验证器函数的__name__,确保每个验证器有唯一标识,避免冲突:
from pydantic import BaseModel, validator import uuid def create_model(additional_data): class CustomModel(BaseModel): name: str additional_field: str # 单独定义验证器函数,而非嵌套在类内部 def validate_name(cls, name): if additional_data == 'some_condition': # 针对该条件的自定义验证逻辑 if len(name) < 5: raise ValueError("名称长度至少为5(some_condition规则)") else: # 其他条件的验证逻辑 if len(name) < 3: raise ValueError("名称长度至少为3(默认规则)") return name # 给验证器设置唯一名称,避免Pydantic判定重复 validate_name.__name__ = f"validate_name_{uuid.uuid4().hex[:8]}" # 将验证器绑定到模型字段 CustomModel.__validators__['name'] = validator('name')(validate_name) return CustomModel # 测试调用 Model1 = create_model("condition1") Model2 = create_model("condition2")
方法二:使用Pydantic官方动态模型工厂(推荐)
直接用Pydantic提供的create_model函数创建动态模型,从根源避免嵌套类带来的函数标识冲突:
from pydantic import BaseModel, validator, create_model def create_model(additional_data): def validate_name(cls, name): if additional_data == 'some_condition': if len(name) < 5: raise ValueError("名称长度至少为5") else: if len(name) < 3: raise ValueError("名称长度至少为3") return name # 动态生成模型,指定字段、验证器 CustomModel = create_model( # 给模型设置唯一名称,方便调试 f"CustomModel_{additional_data}", name=(str, ...), # 必填字符串字段 additional_field=(str, ...), # 绑定验证器 __validators__={ 'name': validator('name')(validate_name) } ) return CustomModel # 测试调用 Model1 = create_model("condition1") Model2 = create_model("condition2")
Pydantic V2 适配写法
如果使用Pydantic V2,需替换validator为field_validator,写法如下:
from pydantic import BaseModel, field_validator, create_model def create_model(additional_data): def validate_name(cls, name): if additional_data == 'some_condition': if len(name) < 5: raise ValueError("名称长度至少为5") else: if len(name) < 3: raise ValueError("名称长度至少为3") return name CustomModel = create_model( f"CustomModel_{additional_data}", name=(str, ...), additional_field=(str, ...), __field_validators__={ 'name': field_validator('name')(validate_name) } ) return CustomModel
内容的提问来源于stack exchange,提问作者sauravshah31
相关产品推荐
相关产品推荐

