如何验证 pydantic 模型的多个领域

新手上路,请多包涵

我想验证 pydantic 模型的三个模型字段。为此,我从 pydantic 导入 root_validator。低于错误。我在 https://pydantic-docs.helpmanual.io/usage/validators/#root-validators 中找到了这个。任何人都可以帮助我。找到下面的错误。 from pydantic import BaseModel, ValidationError, root_validator Traceback(最近调用最后):文件“”,第 1 行,在 ImportError 中:无法从“pydantic”导入名称“root_validator”(C:\Users\Lenovo\AppData\Local\Programs\ Python\Python38-32\lib\site-packages\pydanticinit.py)

我试过

@validator
def validate_all(cls,v,values,**kwargs):

我从一些公共领域的父模型继承了我的 pydantic 模型。值仅显示父类字段,但不显示我的子类字段。例如

class Parent(BaseModel):
    name: str
    comments: str
class Customer(Parent):
    address: str
    phone: str

    @validator
    def validate_all(cls,v,values, **kwargs):
         #here values showing only (name and comment) but not address and phone.

原文由 samba 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.3k
1 个回答

为了扩展 Rahul R 的答案,这个例子更详细地展示了如何使用 pydantic 验证器。

此示例包含回答您的问题的所有必要信息。

请注意,还有使用 @root_validator 的选项,如 Kentgrav 所述,有关更多详细信息,请参阅帖子底部的示例。

 import pydantic

class Parent(pydantic.BaseModel):
    name: str
    comments: str

class Customer(Parent):
    address: str
    phone: str

    # If you want to apply the Validator to the fields "name", "comments", "address", "phone"
    @pydantic.validator("name", "comments", "address", "phone")
    @classmethod
    def validate_all_fields_one_by_one(cls, field_value):
        # Do the validation instead of printing
        print(f"{cls}: Field value {field_value}")

        return field_value  # this is the value written to the class field

    # if you want to validate to content of "phone" using the other fields of the Parent and Child class
    @pydantic.validator("phone")
    @classmethod
    def validate_one_field_using_the_others(cls, field_value, values, field, config):
        parent_class_name = values["name"]
        parent_class_address = values["address"] # works because "address" is already validated once we validate "phone"
        # Do the validation instead of printing
        print(f"{field_value} is the {field.name} of {parent_class_name}")

        return field_value

Customer(name="Peter", comments="Pydantic User", address="Home", phone="117")

输出

<class '__main__.Customer'>: Field value Peter
<class '__main__.Customer'>: Field value Pydantic User
<class '__main__.Customer'>: Field value Home
<class '__main__.Customer'>: Field value 117
117 is the phone number of Peter
Customer(name='Peter', comments='Pydantic User', address='Home', phone='117')

要更详细地回答您的问题:

将要验证的字段添加到验证函数正上方的 @validator 装饰器。

  • @validator("name") 使用字段值 "name" (例如 "Peter" )作为验证函数的输入。该类及其父类的所有字段都可以添加到 @validator 装饰器中。
  • 验证函数 ( validate_all_fields_one_by_one ) 然后使用字段值作为第二个参数 ( field_value ) 来验证输入。验证函数的返回值写入类字段。验证函数的签名是 def validate_something(cls, field_value) 其中函数和变量名称可以任意选择(但第一个参数应该是 cls )。根据 Arjan ( https://youtu.be/Vj-iU-8_xLs?t=329 ),还应该添加 @classmethod 装饰器。

如果目标是通过使用父类和子类的其他(已验证)字段来验证一个字段,则验证函数的完整签名为 def validate_something(cls, field_value, values, field, config) (参数名称 valuesfieldconfig 必须 匹配),其中可以使用字段名称作为键访问字段的值(例如 values["comments"] )。

Edit1 :如果你只想检查某种类型的输入值,你可以使用以下结构:

 @validator("*") # validates all fields
def validate_if_float(cls, value):
    if isinstance(value, float):
        # do validation here
    return value

Edit2 :使用 @root_validator 一起验证所有字段的更简单方法:

 import pydantic

class Parent(pydantic.BaseModel):
    name: str
    comments: str

class Customer(Parent):
    address: str
    phone: str

    @pydantic.root_validator()
    @classmethod
    def validate_all_fields_at_the_same_time(cls, field_values):
        # Do the validation instead of printing
        print(f"{cls}: Field values are: {field_values}")
        assert field_values["name"] != "invalid_name", f"Name `{field_values['name']}` not allowed."
        return field_values

输出

 Customer(name="valid_name", comments="", address="Street 7", phone="079")
<class '__main__.Customer'>: Field values are: {'name': 'valid_name', 'comments': '', 'address': 'Street 7', 'phone': '079'}
Customer(name='valid_name', comments='', address='Street 7', phone='079')

 Customer(name="invalid_name", comments="", address="Street 7", phone="079")
ValidationError: 1 validation error for Customer
__root__
  Name `invalid_name` not allowed. (type=assertion_error)

原文由 wueli 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题