zoukankan      html  css  js  c++  java
  • Meta

    - __mro__
    - 应用:wtforms中meta使用(meta作用定制csrf token)

    示例

    from flask import Flask,request,render_template,session,current_app,g,redirect
    from wtforms import Form
    from wtforms.csrf.core import CSRF
    from wtforms.fields import simple
    from hashlib import md5
    
    from wtforms import widgets
    from wtforms import validators
    
    app = Flask(__name__)
    
    class MyCSRF(CSRF):
        """
        Generate a CSRF token based on the user's IP. I am probably not very
        secure, so don't use me.
        """
    
        def setup_form(self, form):
            self.csrf_context = form.meta.csrf_context()
            self.csrf_secret = form.meta.csrf_secret
            return super(MyCSRF, self).setup_form(form)
    
        def generate_csrf_token(self, csrf_token):
            gid = self.csrf_secret + self.csrf_context
            token = md5(gid.encode('utf-8')).hexdigest()
            return token
    
        def validate_csrf_token(self, form, field):
            print(field.data, field.current_token)
            if field.data != field.current_token:
                raise ValueError('Invalid CSRF')
    
    class LoginForm(Form):
        name = simple.StringField(
            validators=[
                validators.DataRequired(message='用户名不能为空.'),
            ],
            widget=widgets.TextInput(),
            render_kw={'placeholder':'请输入用户名'}
        )
        pwd = simple.PasswordField(
            validators=[
                validators.DataRequired(message='密码不能为空.'),
    
            ],
            render_kw={'placeholder':'请输入密码'}
        )
    
        class Meta:
            # -- CSRF
            # 是否自动生成CSRF标签
            csrf = True
            # 生成CSRF标签name
            csrf_field_name = 'csrf_token'
    
            # 自动生成标签的值,加密用的csrf_secret
            csrf_secret = 'xxxxxx'
            # 自动生成标签的值,加密用的csrf_context
            csrf_context = lambda x: request.url
            # 生成和比较csrf标签
            csrf_class = MyCSRF
       
    '''
        LoginForm._unbound_fields = None
        LoginForm._wtforms_meta = None
        LoginForm.name = UnboundField(creation_counter=1,simple.StringField)
        LoginForm.pwd = UnboundField(creation_counter=1,simple.PasswordField)
        UnboundField的作用:通过creation_counter的值进行排序
    
    '''
    
    
    @app.route('/login',methods=['GET','POST'])
    def login():
        if request.method == "GET":
            form = LoginForm()
            '''
            实例化的时候执行FormMeta的__call__方法
            LoginForm._unbound_fields = [
                    ('name',UnboundField(creation_counter=1,simple.StringField),),
                    ('pwd',UnboundField(creation_counter=2,simple.PasswordField),),
            ]
             LoginForm._wtforms_meta = class Meta(Meta,DefaultMeta):pass
            '''
    
            return render_template('login.html',form=form)
    
        form = LoginForm(formdata=request.form)
        if form.validate():
            print(form.data)
            return redirect('https://www.luffycity.com/home')
        else:
            return render_template('login.html', form=form)
    
    
    if __name__ == '__main__':
        app.run()

    login.html

    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <meta name="viewport" content="width=device-width, initial-scale=1">
    </head>
    <body>
        <form method="post" novalidate>
            {{form.csrf_token}}
            <p>用户名:{{form.name}}  {{form.name.errors[0]}}</p>
            <p>密码:{{form.pwd}}  {{form.pwd.errors[0]}} </p>
            <p><input type="submit" value="提交"  ></p>
        </form>
    </body>
    </html>

    源码:

    # form.py
    class FormMeta(type):
       
        def __init__(cls, name, bases, attrs):
            type.__init__(cls, name, bases, attrs)
            cls._unbound_fields = None
            cls._wtforms_meta = None        (1)
    
        def __call__(cls, *args, **kwargs):
    
            if cls._unbound_fields is None:
                fields = []
                for name in dir(cls):
                    '''
                    fields = [
                        ('name',UnboundField(creation_counter=1,simple.StringField),),
                        ('pwd',UnboundField(creation_counter=2,simple.PasswordField),),
                    ]
                    '''
                    if not name.startswith('_'):
                        unbound_field = getattr(cls, name)
                        if hasattr(unbound_field, '_formfield'):
                            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:
                bases = []
                '''
                [
                    DefaultMeta,
                ]
                '''
    
                for mro_class in cls.__mro__:
                    if 'Meta' in mro_class.__dict__:
                        # DefaultMeta
                        bases.append(mro_class.Meta)
                # cls._wtforms_meta = type('Meta', (Meta,DefaultMeta), {})
    
                cls._wtforms_meta = type('Meta', tuple(bases), {})
            return type.__call__(cls, *args, **kwargs)
    
    
    
    '''
    class NewBase(BaseForm,metaclass=FormMeta):
        pass
    class Form(NewBase)
    
    '''
    class Form(with_metaclass(FormMeta, BaseForm)):
    
        Meta = DefaultMeta
    
        def __init__(self, formdata=None, obj=None, prefix='', data=None, meta=None, **kwargs):
            
            meta_obj = self._wtforms_meta()
            if meta is not None and isinstance(meta, dict):
                meta_obj.update_values(meta)
            super(Form, self).__init__(self._unbound_fields, meta=meta_obj, prefix=prefix)
    
            for name, field in iteritems(self._fields):
                # Set all the fields to attributes so that they obscure the class
                # attributes with the same names.
                setattr(self, name, field)
            self.process(formdata, obj, data=data, **kwargs)
        #……
      
      
        
    # meta.py
    class DefaultMeta(object):
    
        # ……
    
        csrf = False
        csrf_field_name = 'csrf_token'
        csrf_secret = None
        csrf_context = None
        csrf_class = None
        
        #……
       
  • 相关阅读:
    三元运算
    sys and os
    print.format
    while loop
    线段树模板
    Round #431 (Div.2)
    D. Make a Permutation!
    Round #411 (Div.2)
    Round #432 (Div.2)
    Round #433 (Div.2)
  • 原文地址:https://www.cnblogs.com/zh-xiaoyuan/p/13267695.html
Copyright © 2011-2022 走看看