原文:http://www.catonlinepy.tech/
聲明:原創不易,未經許可,不得轉載
1. 你將學會什麼
通過第三天的學習內容,你將對錶單有所瞭解。知道使用插件來處理應用中的表單,以後遇到表單能夠更熟練的使用Flask_WTF插件,並完美的將應用運行起來。今天的學習內容涉及到的代碼都會託管到github上,在學習本課內容時,一定要自己嘗試手敲代碼,遇到問題再到貓姐的github上去查看代碼,如果實在不知道如何去解決問題,可以在日誌下面留言說明具體情況。
2. 表單的插件簡介
WTForms作爲處理Web表單的插件,是一款支持多個web框架的form組件。Flask-WTF插件對其類WTForms進行封裝後以便它能夠與Flask完美的結合。在第三天的內容中,我們將引入第一個Flask插件,後續也會對其它的插件進行引入。要知道,插件用得好,可以使web的開發的過程快到飛起。
大家需知道,所有Flask插件都是屬於Python的三方包,因此都可以使用pip來進行安裝。照舊,我們先進入miao_venv的虛擬環境目錄中,將虛擬環境進行激活,然後安裝Flask_WTF插件。安裝步驟如下:
# 進入到虛擬環境目錄,激活虛擬環境
maojie@Thinkpad:~/flask-plan/$ source miao_venv/bin/activate
# 再安裝Flask_WTF插件
(miao_venv) maojie@Thinkpad:~/flask-plan$ pip install Flask_WTF
3. 表單插件的使用
今天的代碼組織結構如下:
# 使用tree命令查看
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day3$ tree
.
├── form_demo
│ ├── __init__.py
│ ├── routes.py
│ └── templates
│ ├── form.html
│ └── layout.html
└── run.py
現在貓姐來創建今天的課程目錄,步驟如下:
# 在flask-course-primary目錄下創建第三天的課程day3目錄
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary$ mkdir day3
# 進入day3目錄
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary$ cd day3
# 新建form_demo
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day3$ mkdir form_demo
# 進入到form_demo包
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day3$ cd form_demo/
# 在form_demo包中新建__init__.py文件
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day3/form_demo$ touch __init__.py
# 在form_demo新建routes.py路由文件
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day3/form_demo$ touch routes.py
# 在day3目錄下新建run.py文件
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day3/$ touch run.py
上面將課程目錄創建好後,現在我們開始表單的創建。在創建表單之前,貓姐先在__init__.py文件中對Flask_WTF進行配置,如下所示:
# __init__.py文件中的內容
from flask import Flask # 從flask包中導入Flask類
app = Flask(__name__) # 通過Flask類創建一個app實例
app.config['SECRET_KEY'] = 'miaojie is great!' # 對Flask_WTF進行配置
from form_demo import routes
# 解釋:對Flask_WTF進行配置主要是爲了防跨站請求僞造保護。因爲在默認的情況下,Flask_WTF能夠保護所有的表單免受跨站請求僞造的攻擊(Cross-Site Request Forgery,CSRF),但是在特殊情況下,一些惡意網站會把請求發送到被攻擊者已登錄的其它網站時就會發生CSRF攻擊。爲了實現CSRF的保護,Flask_WTF需要程序設置一個密鑰,然後它使用密鑰去生成一個加密令牌,再用令牌驗證請求中的表單數據的真僞。(這裏不懂也沒事,問題不大!)
下面開始一個簡單的Web 表單,貓姐開始利用Flask_WTF插件來創建Web表單,表單內容寫入到routes.py文件中,如下所示:
# routes.py文件中的內容
# 從flask_wtf庫中導入FlaskForm類
from flask_wtf import FlaskForm
# 從wtforms中導入表單的字段對象類
from wtforms import StringField, PasswordField, BooleanField, SubmitField
# 從wtforms.validators字段驗證器中導入DataRequired驗證函數
from wtforms.validators import DataRequired
# LoginForm類函數,繼承自FlaskForm基類
class LoginForm(FlaskForm):
# 表單包括用戶名,密碼和是否記住密碼及一個提交按鈕
username = StringField('Username', validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired()])
remember = BooleanField('Remember Me')
submit = SubmitField('Sign In')
由於只需要用戶輸入用戶名、密碼、記住登錄狀態以及提交按鈕,所以表示web表單的LoginForm僅包含了用戶名,密碼和是否記住密碼可選框以及提交按鈕這4個字段。其中,StringField類表示屬性爲type="text"的<input>元素;PasswordField類表示屬性爲type="password"的<input>元素;BooleanField表示爲true或false的可選框;SubmiteField表示屬性爲type="submit"的<input>元素,而Username,Password,Remember Me表示標籤名稱(label)。在字段類中的可選參數—validators—是一個list變量,可以向類填充不同的校驗函數,它在用戶提交表單按鈕前驗證數據,這裏僅僅只驗證了字段輸入是否爲空。
接下來是表單在前端的渲染,將表單內容添加到模板中,讓瀏覽器進行渲染,用戶在網頁中就可以看到表單了。下面開始進行模板的創建,如下所示:
# 在form_demo中創建templates目錄
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day3/form_demo$ mkdir templates
# 進入templates目錄
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day3/form_demo/$ cd templates
# 創建基模板layout.html
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day3/form_demo/templates$ touch layout.html
# 創建子模板form.html
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day3/form_demo/templates$ touch form.html
在第二課中貓姐已經講到了模板的繼承,在今天的課程中還是用到繼承這個概念。在templates/layout.html中寫入如下代碼:
<!-- layou.html文件中的內容 -->
<html>
<head>
{% if title %}
<title>{{ title }} - 表單的使用-喵星在線</title>
{% else %}
<title>表單的使用-喵星在線</title>
{% endif %}
</head>
<body>
{% block content %}
{% endblock %}
</body>
</html>
然後子模板繼承基模板,在templates/form.html中寫入如下代碼:
<!-- form.html文件中的內容 -->
{% extends "layout.html" %}
{% block content %}
<h1>Sign In</h1>
<form action="" method="post">
# 防跨站僞造請求
{{html_form.hidden_tag() }}
<div>
# 顯示Username標籤名稱
{{ html_form.username.label }}
# Username輸入框
{{ html_form.username() }}
</div>
<div>
# 顯示Password標籤名稱
{{ html_form.password.label }}
# 密碼輸入框
{{ html_form.password() }}
</div>
<div>
# 顯示Remember Me標稱名稱
{{ html_form.remember.label }}
# 是否勾選記住密碼框
{{ html_form.remember() }}
</div>
<div>
# 顯示提交按鈕
{{ html_form.submit() }}
</div>
</form>
{% endblock content %}
通過<form></form>創建表單,它的action屬性告訴瀏覽器用戶在提交表單時將發送請求的URL,當action爲空時,表示請求的是當前的URL頁面,裏面也可以輸入用戶想請求的URL。method屬性指定了表單提交給服務器的HTTP請求方法,因爲裏面要傳送數據,所以請求方法爲post。
上面已經完成了前臺的form表的顯示(渲染)工作,這時就需要在視圖函數中將代表表單的類傳遞到前端模板文件中,這裏是form.html文件。下面在routes.py中編寫視圖函數:
# routes.py文件中的內容
# 從flask庫中導入render_template
from flask import render_template
# 表單內容
# 從flask_wtf庫中導入FlaskForm類
from flask_wtf import FlaskForm
# 從wtforms中導入表單的字段對象類
from wtforms import StringField, PasswordField, BooleanField, SubmitField
# 從wtforms.validators字段驗證器中導入DataRequired驗證函數
from wtforms.validators import DataRequired
# 編寫LoginForm類函數,繼承FlaskForm基類
class LoginForm(FlaskForm):
# 表單包括用戶名,密碼和是否記住密碼及一個提交按鈕
username = StringField('Username', validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired()])
remember = BooleanField('Remember Me')
submit = SubmitField('Sign In')
# 添加視圖函數渲染表單內容
@app.route('/login')
def login():
# 對類LoginForm的實例
form = LoginForm()
# 將視圖函數中的變量form傳到模板form.html文件中去
return render_template('form.html', title='第三天', html_form=form)
現在,所有代碼已編寫完成,通過pythonn run.py(run.py文件的內容與第二天教程的內容相同))將web程序拉起,開始驗證結果,在瀏覽器中輸入http://127.0.0.1:5000/login,效果圖如下所示:
在上面的結果中,貓姐只是完成了表單前臺的渲染,但是還不能在表單中發送數據,下面貓姐將介紹,後臺接收到用戶發送form表單內容後,如何進行處理。
上面的例子中,在表單中輸入用戶名和密碼後,點擊提交按鈕,發現瀏覽器沒有任何反應,後臺程序並不能處理post請求,所以現在需要修改後臺程序routes.py,讓其能夠處理post請求,更改代碼如下:
# routes.py文件中對視圖函數進行修改,處理post語法
# 添加視圖函數渲染表單內容
# 在裝飾器函數中添加http請求方法
@app.route('/login',methods=['GET','POST'])
def login():
# LoginForm的實例化
form = LoginForm()
# 添加處理post請求的代碼
if from.validate_on_subimit():
# 調用flash函數,在flash消息中提示用戶及記住remember狀態成功
flash('登錄用戶 {},記住remember狀態{}成功'.format(form.username.data,form.remember.data), 'success')
# 將視圖函數中的變量form傳到模板form.html文件中去
return render_template('form.html', title='第三天', html_form=form)
# 解釋:flash消息中,form.username.data是獲取表單中的用戶名,form.remember.data是獲取表單中的記住密碼的狀態(它的狀態是true或是false)
當在瀏覽器中點擊提交按鈕後,瀏覽器會發送post請求,就會執行上面的if條件語句,並渲染flash消息到瀏覽器中。瀏覽器默認發送的是get請求,所以當沒有點擊提交按鈕時,就會跳過if語句,直接執行return語句。
但是當你調用flash函數後,在瀏覽器中並沒有渲染flash消息,這是因爲需要將消息渲染到基模板中,才能在所有的子模板中顯示出來。現在來更新layout.html代碼:
<!-- layout.html文件中的內容 -->
<html>
<head>
{% if title %}
<title>{{ title }} - 表單的使用-喵星在線</title>
{% else %}
<title>表單的使用-喵星在線</title>
{% endif %}
</head>
<body>
<!-- 渲染flash消息 -->
{% with messages = get_flashed_messages(with_categories=true) %}
{% if messages %}
{% for category, message in messages %}
<div class="alert alert-{{ category }}">
{{ message }}
</div>
{% endfor %}
{% endif %}
{% endwith %}
{% block content %}
{% endblock %}
</body>
</html>
在瀏覽器中打開網址 http://localhost:5000/,查看結果:
在上圖中就可以將flash的消息渲染出來了,但是,這個flash消息並不會消失,並且顯示效果也不美觀。這是因爲我們沒有給它添加任何css樣式,這個問題在後面的教程中也會講到。
4. 總結
學習完今天的教程,我們掌握瞭如下技能:
- 學習了什麼是表單插件
- 學習瞭如何通過表單插件來創建表單對象
- 學習瞭如何在前端模板中渲染表單對象
- 學習了在視圖函數中處理用戶通過表單發送的post請求
第四天的內容,我們將會帶領大家一起了解使用flask的插件來創建數據庫,怎麼對數據庫進行操作,第三天的內容就到這裏,喜歡的同學們可以在下面點贊留言,或是訪問我的博客地址:http://www.catonlinepy.tech/ 加入我們的QQ羣進一步交流學習!
5. 代碼的獲取
今天的課程就到這裏,大家可以到github上去獲取以上教程中的所有代碼:https://github.com/miaojie19/...
具體下載代碼的命令如下:
# 使用git命令下載flask-course-primary倉庫所有的代碼
git clone https://github.com/miaojie19/flask-course-primary.git
# 下載完成後,進入day3目錄下面,即可看到今天的代碼
cd flask-course-primary
cd day3