回複內容:
瀉藥!
沒看form有關的源碼,但是應該是這樣的∶
首先,你得理解像flask這種MVC(或者說MTC)的基本運行機制。
- 對於flask的view,你得知道wsgi協議(如果不清楚,請自行Google之)。
更底層(邏輯上的底層)的HTTP utils(flask用的是werkzeug)將client端的HTTP requests等進行parse,並且將其構建為wsgi的environment(包含了request及其他資訊)。
wsgi server在process請求的過程是:根據wsgi協議構建environ,將其傳入flask app instance(這個即為flask架構實現的wsgi app),flask app instance用這個environ和自己的``start_response`` method(這個也是uwsgi協議規約)完成請求處理並response。
flask有一個線程級(或greenlet)的request對象。在真正process response之前,將environ丟到這個request對象裡,之後這個request跟著你的那個線程就成為了默契的炮友~~直至response完成或線程完蛋。
views裡面的那一坨坨的route的作用是啥捏?這個就是url routing了,就是我在你的網站上點了一個特定的url,flask要如何滿足你。你得說出你想要的東西吧。
那麼views是什麼時候用到呢?廢話,當然還是在接收並理解請求之後到響應之前。
好了,flask app instance在處理你的需求的時候從request對象裡拿到了你請求的url,這個就相當於一把key,然後app instance根據這個key去views裡找到了對應的鎖(你想要的處理邏輯,就是views裡的route下面的function),這個鎖啊,她一旦被開啟了,滿足你需求的時刻也就快了 ~ ~
P.S. 至於如何匹配到這個鎖的呢,這個就是url mapping了,就是一堆正則匹配(別小看這個,如果你用過flask的blueprint,你會明白寫這麼個mapping也是件爽hi了的事情咯)
- model & controller呢?
你的需求其實就是要flask給你response,response其實呢就是資料(不管是RESTFUL API還是template形式,都是你擼出的data)。
資料這坨翔實怎麼來的呢?就是你從資料庫(廣義,包括sql & nosql db,記憶體級緩衝,磁碟檔案等等等等)拿到的,至於data的來源嘛,可能是你自己插的,或者是從別的地方哭著要來的。
model就是幹這活的,只不過它比較抽象,將資料庫操作轉成了對Python對象的操作(這個就是大名鼎鼎的ORM,其實並沒有什麼卵用,ORM寫多了你連查詢最佳化都忘了,如果你有比較高的performance需求也有很多時間,就自己擼高效檢索方案吧,我沒少被這玩意兒坑%>_<%)。
controller這玩意兒你其實可以不要,不過為了做邏輯分離,讓你擼業務擼的漂亮點兒還是用它吧。
OK,說了這麼多,不知道有沒有人能看懂,如果沒看懂,讓我思考會兒吧 ~ ~
========================================================================
簡而言之呢,你用flask作application的時候,MVC各司其職堆好你產生data的邏輯即可,其它你一概不用管。
靠,終於可以回到你的問題上了:
先看下Form這玩意兒:
from flask.ext.wtf import Formfrom wtforms import StringField, SubmitFieldfrom wtforms.validators import Requiredclass NameForm(Form): name = StringField('What is your name?', validators=[Required()]) submit = SubmitField('Submit')
Flask的request是全域變數(準確點說是線程局部變數,線上程內可以看做是全域變數),我沒有看Flask的form相關的代碼,所有這裡猜測一下,應該是NameForm這個類直接使用到了request.from這個POST表單資料的字典來驗證,又因為request線上程內是全域的,所有NameForm可以不通過參數就可用擷取到表單資料NameForm() 應該是繼承自 WTForm ,先瞭解一下這個東西。
我當初也被搞糊塗了,那本 flask web development裡用到的是flask_wtf模組,而有的教程裡用到的卻是WTForms模組。這是WTForms的表單驗證路由函數@app.route('/register', methods=['GET', 'POST'])def register(): form = RegistrationForm(request.form) if request.method == 'POST' and form.validate(): pass對比二者你會發現,二者有三個區別1.RegistrationForm執行個體化時用到了request.form,而你的例子裡沒有用到。2.你的例子裡沒有驗證表單是POST還是GET方法,上面這個例子裡用了request.method == 'POST'3.一個是form.validate(),一個是form.validate_on_submit()。可見flask_wtf模組裡的Form 類對WTForms裡的Form類進行了封裝。把request.form 和request.method == 'POST'封裝進去了。對比一下代碼應該很容易明白。
試圖簡化解釋一下這個問題:
1、 當路由觸發 index 視圖函數。
form = NameForm() 這條語句建立一個form 執行個體對象,也就是說表單建立了。
2、如果是第一次訪問含有這個表單的頁面 也就是GET請求
if form.validate_on_submit() 這個判斷為假,下面的語句塊不執行。
3、如果是POST請求
這個時候,表單已經存在。
if form.validate_on_submit() 這個判斷為真,下面的語句塊要執行。
name = form.name.data 這條語句在POST的時候,取得form表單屬性值。
4、無論POST、還是GET
return render_template('index.html', form=form, name=name)
這條語句都要被執行。
如何取得form表單的值,請看flask.request。
class flask.requestAPI — Flask Documentation (0.10)
To access incoming request data, you can use the global requestobject. Flask parses incoming request data for you and gives youaccess to it through that global object. Internally Flask makessure that you always get the correct data for the active thread if youare in a multithreaded environment.
This is a proxy. See Notes On Proxies for more information.
The request object is an instance of a Requestsubclass and provides all of the attributes Werkzeug defines. Thisjust shows a quick overview of the most important ones.
可以先看看 @wang Harvey 和 @朱添一 的回答,再去看一下Flask-WTF中定義Form類的源碼,在Form類的注釋裡,https://github.com/lepture/flask-wtf/blob/master/flask_wtf/form.py#L41-L42
這兩行應該能夠清楚解釋題主的問題了。在此引用一下:
If formdata is not specified, this will use flask.request.form.Explicitly pass formdata = None to prevent this.
== 雖然@wang harvey 的答案非常棒,但我覺得完全沒解決樓主的問題啊…………不行,@不上最高票答主了……
樓主不知道 name 是怎麼出來的?那麼 name 是定義出來的。python是強型別,直接定義了 name 來儲存 form.name.data 的資料。
那麼 form.name.data 是怎麼出來的?form.name是你在 form 裡面定義的一個資料,它的 name(參見[文檔]Forms — WTForms 2.0.3dev documentation
)就是 name(你自己定義的) 。
那麼我們把 form.name.data 傳給 name ,有什麼用呢?我們看它是重新導向到 index.html 裡面的,那麼我們開啟 index.html(為了這個我還專門開啟好長時間都沒用的檔案 checkout 了一把),我們可以看到
Hello, {% if name %}{{ name }}{% else %}Stranger{% endif %}!
以下是我的個人理解,首先第一次請求的時候,是get請求,渲染了一個空的表格頁面,當你填完了東西之後,點擊提交就已經是第二次請求,post請求,這時候就把表格的內容發送給伺服器,再進行賦值。題主,我跟你用的同一本書。我是自學程式,看了基本的python文法就強擼這本書了。最開始真的html都不會。。。。。。然後到現在兩個月多了,不好意思才看到第六章第七章。。。