• flask WTForms源码分析及自定义WTForms


    首先我们来创建一个From类

    from wtforms.form import Form
    from wtforms import StringField
    from wtforms.validators import DataRequired
    name = simple.StringField( label='用户名', validators=[ validators.DataRequired(message='用户名不能为空.'), validators.Length(min=6, max=18, message='用户名长度必须大于%(min)d且小于%(max)d') ], widget=widgets.TextInput(), render_kw={'class': 'form-control'} ) # pwd = UnboundField(PasswordField, *args, **kwargs) creation_counter=2 pwd = simple.PasswordField( label='密码', validators=[ validators.DataRequired(message='密码不能为空.'), validators.Length(min=8, message='用户名长度必须大于%(min)d'), validators.Regexp(regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*d)(?=.*[$@$!%*?&])[A-Za-zd$@$!%*?&]{8,}", message='密码至少8个字符,至少1个大写字母,1个小写字母,1个数字和1个特殊字符') ], widget=widgets.PasswordInput(), render_kw={'class': 'form-control'} # 定义css样式 ) class Meta: csrf = False # 是否自动创建csrf def validate_pwd(self,*args,**kwargs): ""验证用户密码"" pass @app.route('/login', methods=['GET', 'POST']) def login(): if request.method == 'GET': return render_template('login.html', form=form) else: form = LoginForm(formdata=request.form) if form.validate(): print('用户提交数据通过格式验证,提交的值为:', form.name.data,form.pwd.data) else: print(form.errors) return render_template('login.html', form=form)

     当代码运行起来之后我们可以看到这样的页面:

    当我们看到这个页面的时候,我们是否想过后台到底发生了什么,为我们生成了这样的页面呢。接下来我们从Form模块的导入来分析:

    首先从导入的Form,这个类是怎么定义的呢:

    class Form(with_metaclass(FormMeta, BaseForm)):
        pass

     一般我们看到的类的继承,都是写一个类,with_metaclass 应该是我们第一次见到,她到底作业什么呢?我们继续查看

    def with_metaclass(meta, base=object):
        # 通过meta创建一个类 并继承base,实际上是继承了两个类(meta,base)
        return meta("NewBase", (base,), {})

    当我们实例化From或From的派生类的时候就会调用FormMeta的,因为FormMeta继承了type并重写了__call__方法,对于类的执行顺序 

    1.  元类的__init__方法
    2. 元类的__call__方法
    3. 自己类或基类的__new__方法
    4. 自己类或基类的__init__方法

     

    所以先执行 FormMeta的init之后执行他的call方法

    class FormMeta(type):
        
        def __init__(cls, name, bases, attrs):
            type.__init__(cls, name, bases, attrs)
            cls._unbound_fields = None
            cls._wtforms_meta = None
    

     

    接下来我们来继续分析FromMeta的call方法

     def __call__(cls, *args, **kwargs):
           
            if cls._unbound_fields is None:  # 第一次为None
                fields = []
                for name in dir(cls):            # 获取类中的所有的静态方法和字段
                    if not name.startswith('_'):    # 排除非私有方法和字段
                        unbound_field = getattr(cls, name)   #反射获取字段名
                        if hasattr(unbound_field, '_formfield'):   # Filed的静态标识
                            fields.append((name, unbound_field))
                # We keep the name as the second element of the sort
                # to ensure a stable sort.
                fields.sort(key=lambda x: (x[1].creation_counter, x[0]))  # 排序
                cls._unbound_fields = fields
    
            # Create a subclass of the 'class Meta' using all the ancestors.
            if cls._wtforms_meta is None:  # 第一次为None
                bases = []
                for mro_class in cls.__mro__:   # 或去派生类的Meta类
                    if 'Meta' in mro_class.__dict__:
                        bases.append(mro_class.Meta)
                cls._wtforms_meta = type('Meta', tuple(bases), {})
            return type.__call__(cls, *args, **kwargs)
    

     元类执行完成之后继续执行执行Form或BaseForm(自身或基类)的__new__和__init__方法

    class BaseForm(object):
       
        def __init__(self, fields, prefix='', meta=DefaultMeta()):
           
            if prefix and prefix[-1] not in '-_;:/.':
                prefix += '-'
            # 初始化字段
            self.meta = meta
            self._prefix = prefix
            self._errors = None
            self._fields = OrderedDict()
    
            if hasattr(fields, 'items'):
                fields = fields.items()
    
            translations = self._get_translations()
            extra_fields = []
            if meta.csrf:
                self._csrf = meta.build_csrf(self)
                extra_fields.extend(self._csrf.setup_form(self))
    
            for name, unbound_field in itertools.chain(fields, extra_fields):
                options = dict(name=name, prefix=prefix, translations=translations)
                field = meta.bind_field(self, unbound_field, options)
                self._fields[name] = field
    

      

      

      

  • 相关阅读:
    mysql 修改字符集
    django 详细实例教程
    mysql 创建数据库
    Django 初始化数据库
    ERROR 1217 (23000): Cannot delete or update a parent row: a foreign key constraint fails
    2019 Multi-University Training Contest 1 D.Vacation(思维)
    2019牛客暑期多校训练营(第五场)E.independent set 1(状压dp)
    2019牛客暑期多校训练营(第三场)A.Graph Games (分块)
    2019牛客暑期多校训练营(第五场)I.three points 1(暴力几何)
    2019牛客暑期多校训练营(第五场)H.subsequence 2(拓扑)
  • 原文地址:https://www.cnblogs.com/richiewlq/p/8270599.html
Copyright © 2020-2023  润新知