第45天:Web表單


                                                             

圖片

在瞭解了 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 必填字段
Email 電子郵箱地址驗證
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

Bootstrap

雖然 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

參考

  • https://flask-wtf.readthedocs.io/en/stable/
  • https://dormousehole.readthedocs.io/en/latest/patterns/wtforms.html
  • https://www.cnblogs.com/haiyan123/p/8254228.html

系列文章

    第44天:Flask 框架集成Bootstrap

    第43天:Python filecmp&difflib模塊

    第42天:Python paramiko 模塊

    第41天:Python operator 模塊

    第0-40天:從0學習Python 0-40合集
相關文章
相關標籤/搜索