场景
常规的数据验证的方式这里就不在赘述了,网上有很多资料。
在实际业务中,有时候出出现这种情况,比如数据库表中有N多个字段,且有M张表,每个输入字段都对应表中的一个字段,并且前后端需要严格校验, 如果我们手写这样的basemodel既费时费力,而且写出的代码臃肿且不易扩展。
所以需要能动态生成basemodel,这样如果表中或者配置中字段有增减就不需要手动修改basemodel类了。
强大的Pydantic提供了这么一种机制。
假设有这种一种场景,从配置或者表中获取待验证的字段,验证从前端输入的值都否在某个范围,且支持分页查询。 某公司员工年龄规定在20~65岁之间,正常薪资范围5000-50000/月
age(20~65)
salary(5000~50000)
配置如下:
config = {
“age”: {“min”: 20, “max”: 65},
“salary”: {“min”: 5000, “max”: “50000”}
}
伪代码实现
from pydantic import create_model, field_validator, BaseModel
# 分页基本模型
class BasePreciseFilterModel(BaseModel):
page: int = 1
page_size: int = 10
# 校验函数
def check_min_max_value(key)
baseline_min_value = config[key]["min"]
baseline_max_value = coofig[key]["max"]
# 这边其实用了一个闭包,用于传入配置中的key,并和这里 v 中传入的前端输入参数中的只做校验
def _check_min_max_value(cls, v):
_min_value_input = v.get("min")
_max_value_input = v.get("max")
if _min_value_input < baseline_min_value:
raise ValueError(...)
if _max_value_input > baseline_max_value:
raise ValueError(...)
return v
return _check_min_max_value
# 生成每个属性的校验器, 这里的 field_validator 实际是一个类装饰器
validators = {
f"{key}_validator": field_validator(key)(check_min_max_value(key))
for key in config.keys()
}
# 动态生成的最终Model类
PreciseSearchFilterModel = create_model(
"PreciseSearchFilterModel ",
**{key: (dict | None, None) for key in config.keys()},
__validators__=validators,
__base__=BasePreciseFilterModel
)
# 接下来就可以应用这个Model类验证输入了, 比如在我们的 Django、Flask、FastApi等项目中。
# 前端传入的payload如下, 搜索年龄在 25~60岁之间,且薪资在10000~20000区间的员工
{"age": {"min": 25, "max": 60}, "salary": {"min": 10000, "max": 20000}, "page":1, "page_size": 5}
@app.route("filter")
def precise_filter(filter: PreciseSearchFilterModel):
filter_params = filter.model_dump()
page = filter_params.pop("page")
page_size = filter_params.pop("page_size")
# TODO 业务逻辑
评论前必须登录!
注册