繁体   English   中英

Pydantic - 如果其中一个字段失败,如何跳过其他字段的验证?

[英]Pydantic - how to skip validation of other fields if one of the fields fails?

假设我有一个像这样的简单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"]键不存在并引发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是否有任何功能会停止进一步验证?

而不是试图在第一个验证器之后停止执行,您可以使用以下内容开始第二个验证器:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM