python-flask-wtforms組件流程源碼

來源:互聯網
上載者:User

標籤:redirect   request   tac   ict   forms   大於   [1]   creation   label   

  在最開始要弄明白一點,類都是由元類建立的。在定義類 class Foo:pass的時候(類也是對象),就會執行type類或者type衍生類別的__init__方法,當Foo()時:執行type類或者type衍生類別的__call__方法,在__call__方法中調用了Foo類的__new__方法建立了一個對象,接著執行__init__方法為這個建立的對象進行賦值屬性。

from flask import Flask, render_template, request, redirectfrom wtforms import Formfrom wtforms.fields import corefrom wtforms.fields import html5from wtforms.fields import simplefrom wtforms import widgetsfrom wtforms import validatorsapp = Flask(__name__, template_folder=‘templates‘)app.debug = True#0 定義LogonForm類class LoginForm(Form):
   #1 StringField類的執行個體化 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 = simple.PasswordField( label=‘密碼‘, validators=[ validators.DataRequired(message=‘密碼不可為空.‘), validators.Length(min=8, message=‘使用者名稱長度必須大於%(min)d‘), validators.Regexp(regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[[email protected]$!%*?&])[A-Za-z\[email protected]$!%*?&]{8,}", message=‘密碼至少8個字元,至少1個大寫字母,1個小寫字母,1個數字和1個特殊字元‘) ], widget=widgets.PasswordInput(), render_kw={‘class‘: ‘form-control‘} ) class Meta: csrf = False def validate_pwd(self,*args,**kwargs): pass@app.route(‘/login‘, methods=[‘GET‘, ‘POST‘])def login(): if request.method == ‘GET‘:
     #2.執行個體化一個LoginForm對象 form = LoginForm() return render_template(‘login.html‘, form=form) else: form = LoginForm(formdata=request.form) if form.validate(): print(‘使用者提交資料通過格式驗證,提交的值為:‘, form.data) else: print(form.errors) return render_template(‘login.html‘, form=form)def test(): form = LoginForm()if __name__ == ‘__main__‘: app.run()

第0步:

在定義LoginForm類的時候我們看看發生了什麼

首先我們要知道metaclass的另外一種方式:with_metaclass

metaclass的另外一種方式:    class MyType(type):        def __init__(self,*args,**kwargs):            print(‘xxxx‘)            super(MyType,self).__init__(*args,**kwargs)        def __call__(cls, *args, **kwargs):            obj = cls.__new__(cls,*args, **kwargs)            cls.__init__(obj,*args, **kwargs) # Foo.__init__(obj)            return obj    def with_metaclass(base):        return MyType("MyType",(base,),{})    class Foo(with_metaclass(object)):        def __init__(self,name):            self.name = name    #列印結果:  xxxx    xxxx

所以我們去Form中找找,發現了metaclass的另外一種方式

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

我們再去with_metaclass看看

def with_metaclass(meta, base=object):    return meta("NewBase", (base,), {})
   # FormMeta("NewBase", (BaseForm,), {}) # 通過FormMeta建立了一個NewBase類,NewBase類繼承了BaseForm類
   # 那你有沒有疑問,為什麼 FormMeta類可以建立類呢? 我們去FormMeta類看看
class FormMeta(type):
  pass
#發現FormMeta繼承了type類,所以剛才我們的疑問迎刃而解。

那就是說當LoginForm定義的時候執行了FormMeta類的__init__方法

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

這步完成後 LoginForm類有兩個屬性:cls._unbound_fields = None和  cls._wtforms_meta = None

第1步:執行個體化StringField類的對象,首先應該去StringField中找__new__方法

 

class StringField(Field):    pass
#發現StringField類中沒有,那我們就去基類中

 

class Field(object):        def __new__(cls, *args, **kwargs):
       #判斷不成立,走else   if ‘_form‘ in kwargs and ‘_name‘ in kwargs:   return super(Field, cls).__new__(cls)   else:
         #返回一個UnboundField對象   return UnboundField(cls, *args, **kwargs)
class UnboundField(object):    _formfield = True    creation_counter = 0    def __init__(self, field_class, *args, **kwargs):        UnboundField.creation_counter += 1        self.field_class = field_class        self.args = args        self.kwargs = kwargs        self.creation_counter = UnboundField.creation_counter    #這個數字,在後面會根據這個進行排序

這步完成後,我們知道 LoginForm的 name和pwd欄位都等於UnboundField 的對象

第2步:執行個體化LoginForm的對象會執行FormMeta的__call__方法

class FormMeta(type):    def __call__(cls, *args, **kwargs):        if cls._unbound_fields is None:            fields = []            #擷取LoginForm類中的所有欄位            for name in dir(cls):                if not name.startswith(‘_‘):                    #擷取該欄位的值                    unbound_field = getattr(cls, name)  #unbound_field 是一個UnboundField對象                    if hasattr(unbound_field, ‘_formfield‘):         #    _formfield = True                        fields.append((name, unbound_field))         # [("name",UnboundField對象),("pwd",UnboundField對象)]            fields.sort(key=lambda x: (x[1].creation_counter, x[0]))  #根據UnboundField對象的creation_counter屬性對fields列表進行排序            cls._unbound_fields = fields                             # LoginForm._unbound_fields = [("name",UnboundField對象),("pwd",UnboundField對象)]        if cls._wtforms_meta is None:            bases = []            for mro_class in cls.__mro__:   #迴圈當前類和基類組成的元組                if ‘Meta‘ in mro_class.__dict__:   #如果類中有Meta類,就把Meta類添加到 bases列表中                    bases.append(mro_class.Meta)            cls._wtforms_meta = type(‘Meta‘, tuple(bases), {})    #LoginForm._wtforms_meta = 一個新的Meta類,它繼承了所有的Meta類,這樣做好處在於:通過新Meta類可以取到無論是LoginForm或者LoginForm基類中的任何Meta類        return type.__call__(cls, *args, **kwargs)

接著到LoginForm或基類中找__new__方法,發現都沒有,那就繼續找LoginForm或基類中的__intit__方法

 

python-flask-wtforms組件流程源碼

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.