Pydantic 验证器无法按预期工作
Pydantic validator does not work as expected
我最近发现了 Pydantic 验证器的强大功能,并开始在我的一个个人项目中使用它们。
但是,我遇到了一个问题:一个验证器失败并没有停止后续验证器的执行,从而导致异常。
class Field(BaseModel):
name: constr(min_length=1, max_length=32)
type: constr(min_length=1, max_length=32)
length: Optional[int]
nullable: bool
class Unique(BaseModel):
name: constr(min_length=1, max_length=32)
unique_fields: List[constr(min_length=1, max_length=32)]
class Resource(BaseModel):
name: constr(min_length=1, max_length=32)
table_name: constr(min_length=1, max_length=32)
fields: List[Field]
primary_key: constr(min_length=1, max_length=32)
uniques: Optional[List[Unique]]
@validator('name')
def resource_name_must_be_pure_string(cls, v):
if not v.isalpha():
raise ValueError(ONLY_ALPHA_ERR.format("Resource name"))
return v
@validator('table_name')
def table_name_must_be_pure_string(cls, v):
if not v.isalpha():
raise ValueError(ONLY_ALPHA_ERR.format("Table name"))
return v
@validator('fields', pre=True)
def field_name_must_be_pure_string(cls, v):
fieldnames = [field["name"] for field in v]
print(fieldnames)
for fieldname in fieldnames:
if not fieldname.replace('_', '').isalpha():
print('was here')
raise ValueError("A field's name can only contain alphabetic characters and '_'.")
return v
@validator('primary_key')
def primary_key_must_be_in_fields(cls, v, values):
fieldnames = [field.name for field in values["fields"]]
if v not in fieldnames:
raise ValueError(f"Primary key `{v}` should be one of the input fields.")
return v
方法 field_name_must_be_pure_string 打印“was here”,因此应该引发 ValueError 异常,但执行继续进行到下一个验证器,它将是 primary_key_must_be_in_fields,因为前面的字段列表无效。
这个极端情况的解决方案是什么?
迟到的答案,但通过使用以下方法设法避免了崩溃:
@validator('primary_key')
def primary_key_must_be_in_fields(cls, v, values):
if "fields" not in values:
return
fieldnames = [field.name for field in values["fields"]]
if v not in fieldnames:
raise ValueError(f"Primary key `{v}` should be one of the input fields.")
return v
花了一段时间才意识到 Pydantic 将进行所有验证并且不会在第一个异常时停止。
我最近发现了 Pydantic 验证器的强大功能,并开始在我的一个个人项目中使用它们。
但是,我遇到了一个问题:一个验证器失败并没有停止后续验证器的执行,从而导致异常。
class Field(BaseModel):
name: constr(min_length=1, max_length=32)
type: constr(min_length=1, max_length=32)
length: Optional[int]
nullable: bool
class Unique(BaseModel):
name: constr(min_length=1, max_length=32)
unique_fields: List[constr(min_length=1, max_length=32)]
class Resource(BaseModel):
name: constr(min_length=1, max_length=32)
table_name: constr(min_length=1, max_length=32)
fields: List[Field]
primary_key: constr(min_length=1, max_length=32)
uniques: Optional[List[Unique]]
@validator('name')
def resource_name_must_be_pure_string(cls, v):
if not v.isalpha():
raise ValueError(ONLY_ALPHA_ERR.format("Resource name"))
return v
@validator('table_name')
def table_name_must_be_pure_string(cls, v):
if not v.isalpha():
raise ValueError(ONLY_ALPHA_ERR.format("Table name"))
return v
@validator('fields', pre=True)
def field_name_must_be_pure_string(cls, v):
fieldnames = [field["name"] for field in v]
print(fieldnames)
for fieldname in fieldnames:
if not fieldname.replace('_', '').isalpha():
print('was here')
raise ValueError("A field's name can only contain alphabetic characters and '_'.")
return v
@validator('primary_key')
def primary_key_must_be_in_fields(cls, v, values):
fieldnames = [field.name for field in values["fields"]]
if v not in fieldnames:
raise ValueError(f"Primary key `{v}` should be one of the input fields.")
return v
方法 field_name_must_be_pure_string 打印“was here”,因此应该引发 ValueError 异常,但执行继续进行到下一个验证器,它将是 primary_key_must_be_in_fields,因为前面的字段列表无效。
这个极端情况的解决方案是什么?
迟到的答案,但通过使用以下方法设法避免了崩溃:
@validator('primary_key')
def primary_key_must_be_in_fields(cls, v, values):
if "fields" not in values:
return
fieldnames = [field.name for field in values["fields"]]
if v not in fieldnames:
raise ValueError(f"Primary key `{v}` should be one of the input fields.")
return v
花了一段时间才意识到 Pydantic 将进行所有验证并且不会在第一个异常时停止。