Validator 类的设计和简单实现

简介: Validator 类的设计和简单实现

一、前置说明


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 装饰器装饰校验方法。

点击进入《Python装饰器从入门到进阶》总目录

目录
相关文章
|
8月前
|
安全 Java
Java反射-Class对象功能概述及反射案例
Java反射-Class对象功能概述及反射案例
77 1
|
Java 数据库连接 Spring
深入了解数据校验(Bean Validation):从深处去掌握@Valid的作用(级联校验)以及常用约束注解的解释说明【享学Java】(下)
深入了解数据校验(Bean Validation):从深处去掌握@Valid的作用(级联校验)以及常用约束注解的解释说明【享学Java】(下)
深入了解数据校验(Bean Validation):从深处去掌握@Valid的作用(级联校验)以及常用约束注解的解释说明【享学Java】(下)
|
8月前
|
Java
Java接口的作用、特点以及常见用法
【2月更文挑战第7天】
121 0
Java接口的作用、特点以及常见用法
|
存储 SQL Java
《JavaSE-第七章》之抽象的类-实例的对象-合理的封装
《JavaSE-第七章》之抽象的类-实例的对象-合理的封装
106 0
【Django学习】(十三)Mixins_各种具体通用类&APIView_ViewSet_GenericViewSet_ModelViewSet类视图继承的父类区别(下)
【Django学习】(十三)Mixins_各种具体通用类&APIView_ViewSet_GenericViewSet_ModelViewSet类视图继承的父类区别(下)
|
算法 Python
【Django学习】(十三)Mixins_各种具体通用类&APIView_ViewSet_GenericViewSet_ModelViewSet类视图继承的父类区别(上)
【Django学习】(十三)Mixins_各种具体通用类&APIView_ViewSet_GenericViewSet_ModelViewSet类视图继承的父类区别
|
Java 索引 Spring
【Spring注解必知必会】深度解析@Component注解实现原理
【Spring注解必知必会】深度解析@Component注解实现原理
455 0
【Spring注解必知必会】深度解析@Component注解实现原理
|
XML 前端开发 Java
深入了解数据校验(Bean Validation):从深处去掌握@Valid的作用(级联校验)以及常用约束注解的解释说明【享学Java】(上)
深入了解数据校验(Bean Validation):从深处去掌握@Valid的作用(级联校验)以及常用约束注解的解释说明【享学Java】(上)
深入了解数据校验(Bean Validation):从深处去掌握@Valid的作用(级联校验)以及常用约束注解的解释说明【享学Java】(上)
|
XML JSON 负载均衡
注解式项目开发!详细分析Java中各个注解的作用和使用方式
本篇文章主要介绍了Java项目中各个注解的作用以及具体使用方式。介绍了Java的框架中每个注解的具体含义以及具体的应用场景。通过了解熟悉Java框架中各个注解的使用方式,可以使我们项目开发工作更加方便高效。
313 0
注解式项目开发!详细分析Java中各个注解的作用和使用方式
|
前端开发 Java Spring
深入了解数据校验(Bean Validation):从深处去掌握@Valid的作用(级联校验)以及常用约束注解的解释说明【享学Java】(中)
深入了解数据校验(Bean Validation):从深处去掌握@Valid的作用(级联校验)以及常用约束注解的解释说明【享学Java】(中)