ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

pydantic验证器

2022-06-16 12:36:31  阅读:287  来源: 互联网

标签:name 验证 validator str BaseModel True pydantic


1.装饰器实现验证器

from pydantic import BaseModel, ValidationError, validator


class UserModel(BaseModel):
    name: str
    username: str
    password1: str
    password2: str

    @validator('name')
    def name_must_contain_space(cls, v):
        if ' ' not in v:
            raise ValueError('must contain a space')
        return v.title()

    @validator('password2')
    def passwords_match(cls, v, values, **kwargs):
        # values:包含任何先前验证的字段的名称到值映射的字典
        if 'password1' in values and v != values['password1']:
            raise ValueError('passwords do not match')
        return v


user = UserModel(
    name='samuel colvin',
    username='scolvin',
    password1='zxcvbn',
    password2='zxcvbn',
)
print(user)
# name='Samuel Colvin' username='scolvin' password1='zxcvbn' password2='zxcvbn'

try:
    UserModel(
        name='samuel',
        username='scolvin',
        password1='zxcvbn',
        password2='zxcvbn2',
    )
except ValidationError as e:
    print(e)
    """
    2 validation errors for UserModel
    name
      must contain a space (type=value_error)
    password2
      passwords do not match (type=value_error)
    """

2.验证器的复杂校验

  • pre=True:前置操做,最先执行的验证器
  • each_item=True:字段遍历:如果所有验证器都没有pre=True,则该验证器最先执行,否则紧跟着具有pre=True的验证器
from typing import List
from pydantic import BaseModel, ValidationError, validator


class DemoModel(BaseModel):
    square_numbers: List[int] = []
    cube_numbers: List[int] = []

    # 1.可以使用'*'来校验所有字段
    # 2.pre=True,可以在验证器前对数据进行预处理,此处如果不处理字符串,下面的验证器在对字段值求和时就会报错
    @validator('*', pre=True)
    def split_str(cls, v):
        if isinstance(v, str):
            return v.split('|')
        return v

    # 3.没有初始化的字段,验证器不会执行
    @validator('cube_numbers', 'square_numbers')
    def check_sum(cls, v):
        if sum(v) > 42:
            raise ValueError('sum of numbers greater than 42')
        return v

    # 4.each_item=True可以实现对字段值的遍历
    @validator('square_numbers', each_item=True)
    def check_squares(cls, v):
        print(v)
        assert v >= 1, f'{v} is not a square number'
        return v


print(DemoModel(square_numbers="1|2|3"))
# print(DemoModel(square_numbers=[1, 4, 9]))

3.子类验证器和each_item

  • 如果将验证程序与引用父类上的类型字段的子类一起使用,将导致验证程序不运行;相反,必须以编程方式对列表进行迭代。each_item=True
from typing import List
from pydantic import BaseModel, ValidationError, validator


class ParentModel(BaseModel):
    names: List[str]


class ChildModel(ParentModel):
    
    # 每个元素必须为空字符串
    @validator('names', each_item=True)
    def check_names_not_empty(cls, v):
        assert v != '', 'Empty strings are not allowed.'
        return v


# This will NOT raise a ValidationError because the validator was not called
try:
    child = ChildModel(names=['Alice', 'Bob', 'Eve', ''])
except ValidationError as e:
    print(e)
else:
    print('No ValidationError caught.')  

# No ValidationError caught.
  • 需要使用循环来处理
class ChildModel2(ParentModel):
    @validator('names')
    def check_names_not_empty(cls, v):
        for name in v:
            assert name != '', 'Empty strings are not allowed.'
        return v


try:
    child = ChildModel2(names=['Alice', 'Bob', 'Eve', ''])
except ValidationError as e:
    print(e)
    """
    1 validation error for ChildModel2
    names
      Empty strings are not allowed. (type=assertion_error)
    """

4.始终验证

  • 验证器在校验字段没有初始化的前提下是不会进行校验的
  • 使用always=True来实现,在没有初始化的前提下,给提供一个动态的默认值
  • 通常情况下与pre=True一起使用
from datetime import datetime

from pydantic import BaseModel, validator


class DemoModel(BaseModel):
    ts: datetime = None

    @validator('ts', pre=True, always=True)
    def set_ts_now(cls, v):
        return v or datetime.now()


print(DemoModel())
# ts=datetime.datetime(2022, 6, 15, 18, 25, 41, 389042)

5.重用验证器

  • 可以实现验证器的复用
from pydantic import BaseModel, validator


def normalize(name: str) -> str:
    return ' '.join((word.capitalize()) for word in name.split(' '))


class Producer(BaseModel):
    name: str

    # 参数需要和model中需要校验的字段保持一致
    # 参数需要和验证器normalize中的形参保持一致
    # 返回值必须提供变量进行接收
    _normalize_p_name = validator('name', allow_reuse=True)(normalize)


class Consumer(BaseModel):
    name: str

    # validators
    _normalize_c_name = validator('name', allow_reuse=True)(normalize)


jane_doe = Producer(name='JaNe DOE')
print(jane_doe.name)
john_doe = Consumer(name='joHN dOe')
print(john_doe.name)
assert jane_doe.name == 'Jane Doe'
assert john_doe.name == 'John Doe'

6.根验证器

  • 实现对整个模型字段进行验证
from pydantic import BaseModel, ValidationError, root_validator


class UserModel(BaseModel):
    username: str
    password1: str
    password2: str

    @root_validator(pre=True)
    def check_card_number_omitted(cls, values):
        assert 'card_number' not in values, 'card_number should not be included'
        return values

    @root_validator
    def check_passwords_match(cls, values):
        pw1, pw2 = values.get('password1'), values.get('password2')
        if pw1 is not None and pw2 is not None and pw1 != pw2:
            raise ValueError('passwords do not match')
        return values


print(UserModel(username='scolvin', password1='zxcvbn', password2='zxcvbn'))

标签:name,验证,validator,str,BaseModel,True,pydantic
来源: https://www.cnblogs.com/puffer/p/16379513.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有