一、前置说明
1、本节目标
- 设计
Validator
类 Validator
类的简单实现
2、相关回顾
二、操作步骤
1、项目目录
atme
:@me
用于存放临时的代码片断或其它内容。pyparamvalidate
: 新建一个与项目名称同名的package,为了方便发布至pypi
。core
: 用于存放核心代码。tests
: 用于存放测试代码。utils
: 用于存放一些工具类或方法。
2、代码实现
pyparamvalidate/core/validator.py
class Validator: def __init__(self, value, field=None, rule_des=None): """ :param value: 待校验的值 :param field: 校验字段 - 用于提示具体哪个字段错误 - 如 'name error: name must be string' - error 前面的 `name` 即为 field :param rule_des: 校验规则描述 """ self.value = value self._field = field self._rule_des = rule_des @staticmethod def _error_prompt(value, exception_msg=None, rule_des=None, field=None): # 优先使用校验方法中的错误提示, 如果方法中没有错误提示,则使用"字段规则描述"进行错误提示, 如果都没有,则用空字符串代替 prompt = exception_msg or rule_des or '' # 拼接出: "TestField" value is invalid due to "test wrong" prompt = f'{field} error: {prompt}' if field else prompt prompt = f'"{value}" is invalid due to "{prompt}"' if prompt else f'"{value}" is invalid.' return prompt def is_string(self, exception_msg=None): """ 校验方法:是否为字符串 :param exception_msg: 校验错误的提示 :return: self - 返回 self 的目的是为了允许链式调用 - 如: Validator(123).is_string().is_empty() """ if not isinstance(self.value, str): raise ValueError(self._error_prompt(self.value, exception_msg, self._rule_des, self._field)) return self def is_not_empty(self, exception_msg=None): if not bool(self.value): raise ValueError(self._error_prompt(self.value, exception_msg, self._rule_des, self._field)) return self
3、测试代码
pyparamvalidate/tests/test_validator.py
import pytest from atme.demo.validator_v1.validator import Validator def test_validator_01(): """ 在 Validator 实例化时,不给 field、rule_des 传值; 在校验方法中,不给 exception_msg 传值 """ validator = Validator('Jane') assert validator.is_string().is_not_empty() with pytest.raises(ValueError) as exc_info: validator = Validator(123) validator.is_string().is_not_empty() assert 'invalid' in str(exc_info.value) print(exc_info.value) # 输出: "123" is invalid. def test_validator_02(): """ 在 Validator 实例化时,给 field、rule_des 传值 """ validator = Validator('Jane', field='name', rule_des='name must be string from rule des.') assert validator.is_string().is_not_empty() with pytest.raises(ValueError) as exc_info: validator = Validator(123, field='name', rule_des='name must be string from rule des.') validator.is_string().is_not_empty() assert 'name must be string from rule des.' in str(exc_info.value) print(exc_info.value) # 输出: "123" is invalid due to "name error: name must be string from rule des." def test_validator_03(): """ 在 Validator 实例化时,给 field、rule_des 传值; 在校验方法中,给 exception_msg 传值 """ validator = Validator('Jane', field='name', rule_des='name must be string from rule des.') assert validator.is_string().is_not_empty() with pytest.raises(ValueError) as exc_info: validator = Validator(123, field='name', rule_des='name must be string from rule des.') validator.is_string('name must be string from method exception msg.').is_not_empty() assert 'name must be string from method exception msg.' in str(exc_info.value) print(exc_info.value) # 输出: "123" is invalid due to "name error: name must be string from method exception msg." def test_validator_04(): """ field_name 为空 """ validator = Validator('Jane', rule_des='name must be string from rule des.') assert validator.is_string().is_not_empty() with pytest.raises(ValueError) as exc_info: validator = Validator(123, rule_des='name must be string from rule des.') validator.is_string('name must be string from method exception msg.').is_not_empty() assert 'name must be string from method exception msg.' in str(exc_info.value) print(exc_info.value) # 输出: "123" is invalid due to "name must be string from method exception msg."
4、日志输出
执行 test
的日志如下,验证通过:
============================= test session starts ============================= collecting ... collected 4 items test_validator.py::test_validator_01 PASSED [ 25%]"123" is invalid. test_validator.py::test_validator_02 PASSED [ 50%]"123" is invalid due to "name error: name must be string from rule des." test_validator.py::test_validator_03 PASSED [ 75%]"123" is invalid due to "name error: name must be string from method exception msg." test_validator.py::test_validator_04 PASSED [100%]"123" is invalid due to "name must be string from method exception msg." ============================== 4 passed in 0.01s ==============================
三、后置说明
1、要点小结
- 按照面向对象的思想设计
Validator
类,其属性包括:value、field、rule_des,分别表示:待校验的数据、该数据对应哪个字段、该字段对应什么规则。其行为包括:is_string()、is_not_empty() 等校验方法; - 校验方法
return self
的目的是为了支持链式调用,如:Validator(input).is_string().is_empty()
。 - 优先使用校验方法中的"错误提示", 如果没有,则使用 “字段规则描述” 代替,最终提示效果:
name error: "123" is invalid. due to: name must be string.
- 每个校验方法中都使用了
if not ... raise ...
,如果校验方法越来越多,重复会越来越明显,可以继续优化。
2、下节准备
- 使用
raise_exception
装饰器装饰校验方法。