自定义python表单验证库

这段时间在做用到tornado的项目,一般那些表单验证都直接交给sqlalchemy或者直接数据库提交捕捉异常,后来想到这种方式对数据的负担较大,而且也不安全,然后对必要的字段都加上了手动的验证
if name:
    return {'state':'error','data':'名称不可为空'}

类似这种验证

写多了后来发不仅不美观规范,而且后期修改和添加验证也很麻烦 ,就产生了写个类似Django里面的form那种表单验证,不过比那个简陋多啦吐舌头

我的习惯是用捕获异常的方式处理这种验证

先明确代码的层次关系

  • UserForm
    • CharField
      • MinLengthValidate
      • MaxLengthValidate
    • IntegerField
      • MaxValueValidate
      • MinValueValidate

类似这种层次关系


明确一下目标
  1. 编写多个验证Validation,用于在Field中复用,比如RequiredValidation(必填验证),minLengthValidation(最小长度验证),拥有自己的validate方法,不满足会抛异常
  2. 编写多个Field,可以加入Validation复用,也有自己的验证,如IntegerField(整数域),CheckListFIeld(选择字段),也拥有自己的validate
  3. 调用Field的validate时会调用他下面所有的Validation的validate方法
  4. 一个Form可以定义许多Field,需要验证的信息以及异常的消息在定义Form时给定,方便service里面调用


异常类
class FormException(Exception):
    pass

定义LoginForm()格式


class LoginForm(BaseForm):
    user = CharField(name='用户名', required=True)
    password = CharField(name='密码', required=True)
    t = CheckField(name='用户类型', required=True, checkList={1, 2, 3})
    checkCode = CharField(name='验证码', required=True)
其中四个字段都为必填,t的值只能在1,2,3中选择

先放测试代码,
</pre></div><pre name="code" class="python">import unittest

from forms import LoginForm
from myExceptions import FormException


class LoginFormTestCase(unittest.TestCase):
    def testLogin1(self):
        try:
            form = LoginForm()
            form.user = 'admin'
            form.password = 'sdfghjkbvcvbn'
            form.checkCode = '12av'
            form.t = 1
            form.validation()
        except FormException, e:
            assert False

    def testLogin2(self):
        try:
            form = LoginForm()
            form.user = 'admin'
            form.password = 'sdfghjkbvcvbn'
            form.checkCode = '12av'
            form.t = 4
            form.validation()
            assert False
        except FormException, e:
            pass

    def testLogin3(self):
        try:
            form = LoginForm()
            form.user = 'admin'
            form.checkCode = '12av'
            form.t = 1
            form.validation()
            assert False
        except FormException, e:
            pass


if __name__ == '__main__':
    unittest.main()

下面放Validation代码
先是基本的父类
class Validation(object):
    def __init__(self):
        self.name = ''
        self.value = ''

    def validation(self):
        pass


各种子Validation
class RequiredValidation(Validation):
    '''
        必填字段验证
    '''

    def validation(self):
        if self.value is None or (
                    (type(self.value) == str or type(self.value) == unicode) and self.value.strip() == '' ):
            raise FormException('%s不可为空' % self.name)


class MaxLengthValidation(Validation):
    '''
        最大长度验证
    '''

    def __init__(self, maxLength):
        self.maxLength = maxLength

    def validation(self):
        if self.value and len(self.value) > self.maxLength:
            raise FormException('%s不可大于%s位' % (self.name, self.maxLength))


class MinLengthValidation(Validation):
    '''
        最小长度验证
    '''

    def __init__(self, minLength):
        self.minLength = minLength

    def validation(self):
        if self.value and len(self.value) < self.minLength:
            raise FormException('%s不可小于%s位' % (self.name, self.minLength))


class MaxValueValidation(Validation):
    '''
        最大数值验证
    '''

    def __init__(self, maxValue):
        self.maxValue = maxValue

    def validation(self):
        if self.value and self.value > self.maxValue:
            raise FormException('%s不可大于%s' % (self.name, self.maxValue))


class MinValueValidation(Validation):
    '''
        最小数值验证
    '''

    def __init__(self, minValue):
        self.minValue = minValue

    def validation(self):
        if self.value and self.value < self.minValue:
            raise FormException('%s不可小于%s' % (self.name, self.minValue))

下面是Field
先是父Field
class Field(object):
    name = ''
    value = ''

    def __init__(self, name):
        self.name = name
        self.validations = []


    def __setattr__(self, key, value):
        object.__setattr__(self, key, value)

        if key == 'value':
            for val in self.validations:
                val.__setattr__(key, value)


    def add_validations(self, validation):
        validation.name = self.name
        self.validations.append(validation)


    def validation(self):
        for val in self.validations:
            val.validation()

发现在重载魔法方法过程中,调用object的魔法方法是个不错的选择 大笑

下面是子Field
lass IntegerField(Field):
    def __init__(self, name='', required=False, maxValue=None, minValue=None):
        Field.__init__(self, name)

        if required:
            self.add_validations(RequiredValidation())
        if not maxValue is None:
            self.add_validations(MaxLengthValidation(maxValue))
        if not minValue is None:
            self.add_validations(MinLengthValidation(minValue))


    def validation(self):
        Field.validation(self)
        if self.value and (not util.is_int(str(self.value))):
            raise FormException('%s不是整数' % self.name)


class FloatField(Field):
    def __init__(self, name='', required=False, maxValue=None, minValue=None):
        Field.__init__(self, name)
        if required:
            self.add_validations(RequiredValidation())
        if not maxValue is None:
            self.add_validations(MaxLengthValidation(maxValue))
        if not minValue is None:
            self.add_validations(MinLengthValidation(minValue))

    def validation(self):
        Field.validation(self)
        if self.value and (not util.is_float(str(self.value))):
            raise FormException('%s不是小数' % self.name)


class EmailField(Field):
    def __init__(self, name='', required=False):
        Field.__init__(self, name)

        if required:
            self.add_validations(RequiredValidation())

    def validation(self):

        Field.validation(self)
        regex = re.compile("^[a-zA-Z0-9_\.]+@[a-zA-Z0-9-]+[\.a-zA-Z]+$")
        if self.value and (not regex.match(self.value)):
            raise FormException('%s不是邮箱格式' % self.name)


class UrlField(Field):
    def __init__(self, name='', required=False):
        Field.__init__(self, name)
        if required:
            self.add_validations(RequiredValidation())


    def validation(self):

        Field.validation(self)
        regex = re.compile(
            "^(http|https|ftp)\\://([a-zA-Z0-9\\.\\-]+(\\:[a-zA-Z0-9\\.&%\\$\\-]+)*@)?((25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9])\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[1-9]|0)\\.(25[0-5]|2[0-4][0-9]|[0-1]{1}[0-9]{2}|[1-9]{1}[0-9]{1}|[0-9])|([a-zA-Z0-9\\-]+\\.)*[a-zA-Z0-9\\-]+\\.[a-zA-Z]{2,4})(\\:[0-9]+)?(/[^/][a-zA-Z0-9\\.\\,\\?\\'\\\\/\\+&%\\$\\=~_\\-@]*)*$")

        if self.value and not (regex.match(self.value)):
            raise FormException('%s不是url格式' % self.name)


class CheckField(Field):
    def __init__(self, name='', required=False, checkList={}):
        Field.__init__(self, name)
        self.checkList = checkList
        if required:
            self.add_validations(RequiredValidation())

    def validation(self):
        Field.validation(self)
        if self.value and (not self.value in self.checkList):
            raise FormException('%s不是合法值' % self.name)


class BirthdayField(Field):
    def __init__(self, name='', required=False):
        Field.__init__(self, name)
        if required:
            self.add_validations(RequiredValidation())

    def validation(self):
        Field.validation(self)
        regex = re.compile("^\d{4}[\-|\s+|/]\d{1,2}[\-|\s+|/]\d{1,2}$")
        if self.value and (not regex.match(self.value)):
            raise FormException('%s不是生日格式' % self.name)


class RegexField(Field):
    def __init__(self, name='', required=False, regex=''):
        Field.__init__(self, name)
        self.regex = regex
        if required:
            self.add_validations(RequiredValidation())

    def validation(self):
        Field.validation(self)
        regex = re.compile(self.regex)
        if self.value and (not regex.match(self.value)):
            raise FormException('%s格式错误' % self.name)


class JsonField(Field):
    def __init__(self, name='', required=False, regex=''):
        Field.__init__(self, name)
        self.regex = regex
        if required:
            self.add_validations(RequiredValidation())

    def validation(self):
        Field.validation(self)
        if self.value:
            try:
                ujson.loads(self.value)
            except Exception, e:
                raise FormException('%s格式错误' % self.name)







写了一些比较常用的Field验证

最后还有个最大的Form
父Form
class BaseForm(object):
    def __init__(self):
        for key in [x for x in dir(self) if isinstance(object.__getattribute__(self, x), Field)]:
            object.__setattr__(self, key, copy.deepcopy(self.__getattribute__(key)))

    def setWithDict(self, d):
        fieldKeys = [x for x in dir(self) if isinstance(object.__getattribute__(self, x), Field)]
        for key, value in d.items():
            if key in fieldKeys:
                self.__setattr__(key, value)

    def __setattr__(self, key, value):

        field = object.__getattribute__(self, key)

        field.value = value

    def validation(self):
        for key in [x for x in dir(self) if not x.startswith('_')]:
            if isinstance(object.__getattribute__(self, key), Field):
                field = object.__getattribute__(self, key)

                field.validation()


也就是调用Form的validation会调用他所有属性Field的validation方法,
在这值得一提的是
我一开始并没有重载__init__,后来发现创建的Form里面的属性竟是同一个对象,验证时会互相覆盖修改!
这是我不希望看到的,主要是因为类的定义属性那边引用赋值了,最后在__init__方法里面复制了对象

这样写完了后既可以进行验证,会抛出实现规定好的异常信息
OVER







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值