首页 > 其他分享 >pydantic做参数校验

pydantic做参数校验

时间:2024-07-31 16:32:38浏览次数:14  
标签:info raise title 校验 PydanticValidationError Field 参数 type pydantic

定义一个统一的schema类对提交的业务参数进行格式和数据约束非常有必要,
下面使用 pydantic 来封装此工具;

import logging
from pydantic import BaseModel, ValidationError, root_validator

class PydanticValidationError(Exception):
    def __init__(self, msg):
        self.message = msg


class BaseSchema(BaseModel):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    class Config:
        anystr_strip_whitespace = True
        use_enum_values = True
        arbitrary_types_allowed = True

    @root_validator(pre=True)
    def _pre_empty_data(cls, values: dict):
        """将空字符串或null字符串转换为None"""
        for k, v in values.items():
            if v == "" or v == "null":
                values[k] = None
        return values

    @classmethod
    def data_validation(cls, data):
        """参数校验,并自定义返回信息"""
        # TODO 这里并不一定是全部的,后面如果碰到其他的,再添加
        try:
            res = cls.parse_obj(data)
            errs = []
        except ValidationError as e:
            res = None
            errs = e.errors()
        for err in errs:
            logging.exception(err)
            fields = list(err["loc"])
            field = fields[0]
            field_info = cls.__fields__.get(field).field_info  # type: ignore
            type_info = err["type"].split(".")
            fields[0] = field_info.title if field_info.title else field
            title = ">>".join([str(tmp) for tmp in fields])
            if len(type_info) == 2:
                if type_info[0] == "type_error" and type_info[1] == "enum":
                    raise PydanticValidationError(f"{title}数据错误,请传指定可选值")
                if type_info[0] == "type_error":
                    raise PydanticValidationError(f"{title}数据类型错误,需要是{type_info[1]}类型")
                if type_info[0] == "value_error" and type_info[1] == "missing":
                    raise PydanticValidationError(f"{title}不能为空")
                if type_info[0] == "value_error" and type_info[1] == "const":
                    raise PydanticValidationError(f"{title}数据错误,请传指定值")
                if type_info[0] == "value_error" and type_info[1] == "ipv4address":
                    raise PydanticValidationError(f"{title}数据错误,需要是ipv4地址")
            if len(type_info) == 3:
                if type_info[2] == "not_gt":
                    raise PydanticValidationError(f"{title}的数值必须大于{field_info.gt}")
                if type_info[2] == "not_lt":
                    raise PydanticValidationError(f"{title}的数值必须小于{field_info.lt}")
                if type_info[2] == "not_ge":
                    raise PydanticValidationError(f"{title}的数值必须大于或等于{field_info.ge}")
                if type_info[2] == "not_le":
                    raise PydanticValidationError(f"{title}的数值必须小于或等于{field_info.le}")
                if type_info[2] == "min_length":
                    raise PydanticValidationError(f"{title}的最小字符长度为{field_info.min_length}")
                if type_info[2] == "max_length":
                    raise PydanticValidationError(f"{title}的最大字符长度为{field_info.max_length}")
                if type_info[2] == "min_items":
                    raise PydanticValidationError(f"{title}中的最少需要{field_info.min_items}个元素")
                if type_info[2] == "max_items":
                    raise PydanticValidationError(f"{title}中的最多只能{field_info.min_items}个元素")
                if type_info[1] == "none" and type_info[2] == "not_allowed":
                    raise PydanticValidationError(f"{title}不能为空")
            raise PydanticValidationError(f"{title}参数错误")
        return res

定义一个schema来接收参数, 它继承BaseSchema

class VictimOrgSchema(BaseSchema):
    title: str = Field(max_length=50, title="组织名称", description="组织名称")
    street: Optional[str] = Field(max_length=255, title="街道具体地址", description="街道具体地址", default="")
    latitude: str = Field(description="经度")
    longitude: str = Field(description="纬度")
    first_id: Optional[int] = Field(description="一级总指挥id")
    second_id: Optional[int] = Field(description="二级总指挥id")
    third_id: Optional[int] = Field(description="三级总指挥id")
    department_id: Optional[int] = Field(title="行业性质",description="行业性质")
    org_nature: int = Field(title="组织性质",description="组织性质")
    contacts: Optional[str] = Field(max_length=255, title="联系人", description="联系人")
    phone: Optional[str] = Field(max_length=11, title="联系电话", description="联系电话")
    logo: Union[FileStorage, str, None] = Field(description="logo")
    province: int = Field(description="省份code")
    city: int = Field(description="城市code")
    team_target: int = Field(description="是否靶标单位", default=0)

view里面进行参数校验

args = dict(request.form) if request.form else {}
data_obj = VictimOrgSchema.data_validation(args)

标签:info,raise,title,校验,PydanticValidationError,Field,参数,type,pydantic
From: https://www.cnblogs.com/gatling/p/18334910

相关文章

  • 如何使用python输入提示具有相同参数类型但不同返回类型的函数?
    我有一个函数,它的返回类型是tuple[bool,set[int]|str]如果第0项是True,则第1项是结果set[int],否则第1项是一个str,显示失败的原因。是这样的defcallee(para_a:int)->tuple[bool,set[int]|str]:result=set([1,2,3])if......
  • 【第二篇章】优秀的机器学习策略 超参数优化之决策树
    在机器学习的浩瀚星空中,决策树作为一颗璀璨的星辰,以其直观易懂、解释性强以及高效处理分类与回归任务的能力,赢得了众多数据科学家与工程师的青睐。随着大数据时代的到来,如何从海量数据中提炼出有价值的信息,构建出既准确又可靠的预测模型,成为了机器学习领域不断探索的热点。......
  • 指示参数应该是可变引用
    使用PEP484和585中指定的类型提示语法,是否有任何方法可以指示函数的参数应该是由函数修改的可变引用?例如,C#有ref参数,因此在Python,有等效的吗?例如>>>deffoo(spam:"Mutable[List[int]]"):...spam.append(sum(spam))...>>>a=[1,2,3]>>>foo(a......
  • 相同类型的多个参数的类型提示?
    除了:deffoobar(a:int,b:int,c:int,d:str):...也许有类似:deffoobar([a,b,c]:int,d:str):...显然是概念性的,但可以减少重复类型提示的方法之外,还有另一种方法可以输入相同类型的提示参数Python中没有像建议的那样直接将多个参数分组到单个类型提......
  • 类型错误:下一个预计至少有 1 个参数,但得到 0
    在我一直在开发的应用程序中,我将其设置为具有三个窗口。当我单击第一页上的按钮打开一个新窗口时,它告诉我一个类型错误。我不明白,因为我将函数设置为“下一个”'没有任何争论。这是代码:fromtkinterimport*fromttkbootstrap.constantsimport*importttkboot......
  • 如何在 pytest 的参数化中传递函数名称以及如何在测试用例中使用它?
    在下面的脚本中,我想参数化函数调用RegisterClientCabinMovementDetection(x)和RegisterClientOccupantInSeatDetection(x)(在脚本中以粗体显示)等等...有没有办法在pytest中参数化函数?@[email protected]('Qf,预期',[(UNDEFINED,"无效"),(INPROGR......
  • python函数:带星号的参数一个接一个
    我想知道为什么定义以下函数被认为是好的。deffoo(*x,y):pass据我所知,现在有调用此函数的方法,因为它总是缺少y的值。(如果我错了,请纠正我。)这有什么我不知道的用处吗?你说得对,在Python中定义一个像deffoo(*x,y):...这样的函数,在试图以常规方......
  • 参数传递
    publicclassCanShuDemo{publicstaticvoidmain(String[]args){inta=10;intb=20;System.out.println("a:"+a+",b:"+b);//a:10,b:20change(a,b);System.out.println("a:&qu......
  • xtrabackup 常用参数详细介绍
    参数值参数用途–print-defaults输出mysql实例的参数配置信息–no-defaults不从任何配置文件中读取参数信息,除了登录文件–defaults-file=#仅从指定的配置文件读取参数–defaults-extra-file=#......
  • 为什么模型中的梯度参数全部都是None?
    这是我的模型。我的计划是制作一个融合相机和雷达图像的模型。classFusionNet(nn.Module):def__init__(self,radar_channels=1,camera_channels=3,n_classes=2,bilinear=False):super(FusionNet,self).__init__()self.radar_channels=radar_c......