PydantiC语言 如果其中一个字段失败,如何跳过其他字段的验证?



假设我有一个简单的pydantic.BaseModel:

from myapp import User
from pydantic import BaseModel, validator
class ChangePasswordRequest(BaseModel):
class Config:
arbitrary_types_allowed = True  # because I'm using my `User` arbitrary type
user: User
current_password: constr(min_length=1, max_length=255)
new_password: constr(min_length=8, max_length=64)

@validator("user")
def user_is_active(cls, user: User):
assert not user.inactive, "User is not active."
return user
@validator("current_password")
def current_password_validator(cls, password: str, values: Dict[str, Any]):
user: User = values["user"]
assert user.check_password(password), "current_password is not valid."
return password

这是我想用来处理用户密码更改的模型。当我用inactive用户创建ChangePasswordRequest时,我得到一个KeyError,因为pydatinc验证所有字段。

from myapp import User
user = User(inactive=True)
r = ChangePasswordRequest(user=user, current_password="current", new_password="new-password")
# I get
KeyError: 'user'

发生的原因:

  • user_is_active被调用,验证失败。values["user"]未设置为效果
  • 调用
  • current_password_validator
  • values["user"]key不存在,KeyError被抛出。

我想实现的是,如果user字段验证失败,则跳过所有验证,因为没有进一步验证的意义。对于像我这样的小模型来说,这不是问题,因为我可以在每个验证器中添加if语句,但随着模型的增长,这变得很恼人。


@validator("current_password")
def current_password_validator(cls, password: str, values: Dict[str, Any]):
if not user := values.get("user"):
return password
assert user.check_password(password), "current_password is not valid."
return password

另一种方法是使用root_validator(pre=True),但这种方法还有另一个问题。错误位于__root__字段,而不是user字段。

@root_validator(pre=True)
def user_is_active(cls, values: Dict[str, Any]):
user: Union[User, None] = values.get("user", None)
assert getattr(user, "is_active", False), "User is not active."
return values
# which produces following error:
[{'loc': ['__root__'],
'msg': 'User is not active.',
'type': 'assertion_error'}]

pydantic是否有任何功能,如果其中一个"主"或";crucial"领域的失败?

与其尝试在第一个验证器之后停止执行,不如这样开始第二个验证器:

if "user" not in values:
raise ValueError("Could not validate current_password because user did not pass validation")