在瞭解了 Flask Bootstrap 基本框架以後,咱們來了解一下 Flask 框架的 表單( form ),以幫助咱們建立交互式的 Web 應用,最後會有個提交我的信息的例子。css
Flask-WTF 是 Flask 框架的一個擴展,用來作表單的交互,是對 WTForms 的集成,默認支持 CSRF 安全簽名,而且繼承文件上傳功能。html
使用 pip 安裝flask
pip install Flask-WTF
驗證bootstrap
>>> from flask_wtf import FlaskForm>>>
Flask-WTF 能將 WTForms 集成到 Flask 應用中,建立一個 app.py
主代碼文件,例如:安全
from flask_wtf import FlaskFormfrom wtforms import StringFieldfrom wtforms.validators import DataRequired
class MyForm(FlaskForm): name = StringField('name', validators=[DataRequired()])
MyForm 是自定義的類,繼承自 FlaskForm,其中定義了一個字段 name,標題是 name, 且設置爲非空。服務器
接下來建立一個表單模板 submit.html
,例如:app
<form method="POST" action="/"> {{ form.csrf_token }} {{ form.name.label }} {{ form.name(size=20) }} <input type="submit" value="Go"></form>
其中 form.csrf_token
是 Flask-WTF 提供的一個防止跨站請求僞造的隱藏字段。原理是將一個密鑰根據請求特徵加密,在表單提交時一塊兒送到服務器端,做校驗。框架
密鑰串與多種定義方式,爲了方便,這裏將密鑰串定義在應用上:ide
app.secret_key = 'abc'
注意:上示例僅做演示說明,不能在生產系統中用這樣簡單的密鑰函數
以後則是對字段 name
的模板定義,通過渲染會替換成 Html 控件。
視圖函數首先須要將表單渲染出來,另外要對錶單的提交做驗證,固然視圖函數與提交驗證函數也可不是同一個:
@app.route('/', methods=('GET', 'POST'))def submit(): form = MyForm() if form.validate_on_submit(): return redirect('/success') return render_template('submit.html', form=form)
提交表單通常都是 POST 方法,因此要確保視圖函數支持 POST
視圖函數中實例化一個 MyForm,值得注意的時,FlaskForm 示例化時會使用 request 中的 form 來初始化,因此在下面才能夠直接來校驗表單
validate_on_submit 方法是 is_submitted 和 validate 的聯合校驗,後面會詳述
若是驗證經過將跳轉到 /success
,若是沒有經過,用 form 來渲染 submit.html
模板,
在主代碼 app.py
中加入啓動方法:
if __name__ == '__main__': app.run(debug=True)
而後運行,若是一塊兒正常,訪問 localhost:5000
, 就能看輸入框和提交按鈕,點擊提交,會跳轉到 /success
或者提高必填。
FlaskForm 是 WTForms Form 的子類,能夠用來定一個表單,定義表單中的字段,驗證方式等,做爲一個 Flask 和 Html 之間的一個數據載體。
另外 FlaskForm 集成了 CSRF 校驗,方便編寫程序的同時,提升訪問安全性。定義 Form 對象時不用明確聲明 CSRF 字段,只須要在表單模板中填寫 form.csrf_token
就行,提交表單時,視圖函數會自動對 CSRF 進行校驗。
FlaskForm 實例化參數中有個 formdata 參數,用來設定 Form 中字段的值,在視圖函數中,能夠不提供 formdata,會將 request.form 或者 request.files 中獲取,做爲 formdata 參數,這就是視圖函數中實例化 Form 時,不帶任何參數,在後面還能方法 Form 對象內容的緣由。
FlaskForm 從 0.9.0 版本開始,再也不從 WTForms 中導入任何東西,因此大部分字段和校驗方法都直接引用自 WTForms,如:
from wtforms import StringField, IntergreField, validators
字段 | 說明 |
---|---|
StringField | 文本字段 |
IntergreField | 文本字段,要求輸入的時數字 |
PasswordField | 文本字段,輸入內容會轉會爲小黑點 |
DateField | 文本字段,輸入指定日期格式的字符串會轉會爲日期類型 |
RadioField | 單選字段 |
SelectField | 選擇字段 |
SelectMultipleField | 多項選擇字段 |
SubmitField | 表單的提交按鈕 |
驗證 | 說明 |
---|---|
DataRequired | 必填字段 |
電子郵箱地址驗證 | |
EqualTo | 驗證與其餘指定字段值是否相等 |
Length | 輸入字符串長度限制 |
NumberRange | 輸入數值大小限制 |
URL | 網站格式驗證 |
例如定義一個 MyForm 表單類:
class MyForm(FlaskForm): name = StringField(label='姓名', validators=[InputRequired()]) city = StringField('城市', validators=[validators.Length(min=4, max=25, message='輸入的長度不符合要求')]) birthday = DateField(label='生日', format="%Y-%m-%d", validators=[DataRequired('日期格式不正確')]) gender = RadioField(label='性別', choices=[(1, 'male'), (2, 'female')]) interest = SelectMultipleField(label='興趣', choices=[(1, 'Football'), (2, 'Movies'), (3, 'Reading')])
若是字段值驗證失敗,會將錯誤信息存放在字段的 errors
屬性中,errors
是個列表,元素是每個驗證出現的問題信息,經過設定驗證的 message
參數指定。
要完整的在模板中定義字段以及錯誤信息,是件乏味的事情,這裏經過一個自定義的模板宏來完成:
{% macro render_field(field) %} <dt>{{ field.label }}: <dd>{{ field(**kwargs)|safe }} {% if field.errors %} <ul> {% for error in field.errors %} <li>{{ error }}</li> {% endfor %} </ul> {% endif %} </dd>{% endmacro %}
上傳文件,是表單應用必不可少的,能夠經過 FileField 字段來設置,由於須要視圖函數對上傳的文件進行處理,因此這裏單獨做說明
定義一個有上傳文件字段的表單類:
from flask_wtf.file import FileField
class PhotoForm(FlaskForm): photo = FileField('上傳照片')
視圖函數定義爲:
@app.route('/upload', methods=['GET', 'POST'])def upload(): form = PhotoForm() filepath = None if form.validate_on_submit(): filename = secure_filename(form.photo.data.filename) file = form.photo.data filepath = os.path.join(app.config['UPLOAD_FOLDER'], filename) file.save( filepath ) else: filename = None return render_template('photo.html', form=form, filename= filename)
在經過驗證以後,用方法 secure_filename
對上傳文件名做安全處理,這是頗有必要的,以防止經過文件名注入, 這個方法從庫 werkzeug
中導入,這個庫會在在安裝 Flask
時一塊兒被安裝。
以後拿到上傳文件的數據,這是已經通過 Flask 轉化的 File 對象,能夠直接調用 save 方法存儲上傳的文件。
app.config['UPLOAD_FOLDER']
定義了文件存儲的位置,如:
app.config['UPLOAD_FOLDER'] = './upload'
最後新建一個模板文件 upload.html:
<form action="/upload" method="post" enctype="multipart/form-data"> {{ form.csrf_token() }} {{ form.photo() }} <input type="submit" value="提交"></form>
注意模板中 form
的編碼類型必須設置爲 multipart/form-data
雖然 FlaskForm 使用起來已經很方便了,可是仍是有不少須要重複編寫的地方,以及展現效果不夠美觀的問題,藉助 Bootstrap-flask
將解決這些問題。
以前對 Bootstrap-flask
介紹中說國,Bootstrap-flask
主要是定義了不少模板宏,減小重複的編碼,對於表單,一樣提供了不少宏
首先在模板中導入 bootstrap 的 Form 相關宏:
{% from 'bootstrap/form.html' import render_form, render_form_row, render_field %}
render_form
接受一個 Form 對象,將其渲染成 Html 表單,是最省事的,例如:{{ render_form(form) }}
render_field
接受一個 Field, 將其渲染成一個表單的字段:{{ render_field(form.name) }}
render_form_row
接受一個 Field 列表,將列表中的字段渲染到一行模板代碼以下:
{% from 'bootstrap/form.html' import render_form, render_form_row, render_field %}{{ bootstrap.load_css() }}<h1> render_form </h1>{{ render_form(form) }}
<h1>render_form_row</h1><form method="post" > {{ render_form_row([form.name, form.city]) }} {{ render_form_row([form.gender, form.birthday]) }} {{ render_form_row([form.interest]) }}</form>
<h1>render_field</h1><form method="post" > {{ render_field(form.name) }} {{ render_field(form.gender) }} {{ render_field(form.interest) }}</form>
先導入表單相關的宏,而後加入 Bootstrap 的樣式,以後是各個宏的使用
本節課程簡單介紹了 Flask 中表單的處理方式和方法,包括 FlaskForm,WTForms和一些經常使用的字段,最後說明了 Bootstrap-flask 對錶單的支持,以即是 Web 開發更高效。
示例代碼:Python-100-days-day045
參考
系列文章
第0-40天:從0學習Python 0-40合集