pip install flask-wtfhtml
from flask_wtf import Form from wtforms import StringField from wtforms.validators import DataRequired class MyForm(Form): user = StringField('Username', validators=[DataRequired()])
表單類MyForm定義個了一個字符型字段,也就是一個文字輸入框」user」。StringField的第一個參數」Username」指定了該字段的顯示名,第二個參數指定了驗證規則。這是一個列表,也就是你能夠對一個字段定義多個驗證規則,上例中咱們使用了」wtforms.validators.DataRequired」驗證,也就是表明了該字段爲必填項,表單提交時必須非空。正則表達式
下一步,咱們寫個視圖函數login來使用MyForm表單flask
from flask import Flask, render_template app = Flask(__name__) app.secret_key = '1234567' @app.route('/login', methods=('GET', 'POST')) def login(): form = MyForm() if form.validate_on_submit(): # if form.user.data == 'admin': if form.data['user'] == 'admin': return 'Admin login successfully!' else: return 'Wrong user!' return render_template('login.html', form=form)
有了這個」form.validate_on_submit()」方法,咱們就不用像以前同樣經過請求方法是否爲」POST」來判斷表單是否提交。在表單提交後,咱們能夠用表單對象的data屬性來獲取提交內容,這個」form.data」是一個字典類型。上例中,它只有一個字段,也就是」user」。咱們一樣也能夠用」form.user.data」獲取」user」字段的值。在非提交狀態下,咱們就渲染模板,而且往模板中傳入表單對象。另外注意,這裏要設置」app.secret_key」,由於表單類中會使用到會話對象session。瀏覽器
最後讓咱們寫」login.html」模板來顯示這個表單:安全
<form method="POST" action="{{ url_for('login') }}"> {{ form.hidden_tag() }} {{ form.user.label }}: {{ form.user(size=20) }} <input type="submit" value="Submit"> </form>
表單中,」form.hidden_tag()」會生成一個隱藏的」<div>」標籤,其中會渲染任何隱藏的字段,最主要的是CSRF字段。這個CSRF(Cross-Site Request Forgery跨站請求僞造)是一種經過假裝來自受信任用戶的請求,來發送惡意攻擊的方法,具體內容你們能夠在網上搜到。WTForms默認開啓CSRF保護,若是你想關閉它(建議不要這樣作),能夠在實例化表單時傳入參數,好比」form = MyForm(csrf_enabled=False)」。babel
「form.user.label」會輸出」user」字段的顯示名,即上例中的」Username」;」form.user」會輸出一個」text」類型的」<input>」標籤,它的參數」size=20″會成爲這個」<input>」標籤裏的屬性。因此上面的模板內容在渲染後,會被轉換爲下面這段HTML代碼:session
<form method="POST" action="/login"> <div style="display:none;"><input id="csrf_token" name="csrf_token" type="hidden" value="1458707165##33a1f1384d3c12dca29cce5e8ccf6e4d21f5f28f"></div> <label for="user">Username</label>: <input id="user" name="user" size="20" type="text" value=""> <input type="submit" value="Submit"> </form>
運行返回以下結果app
當咱們輸入」admin」時,返回成功;輸入其餘字符串時,返回失敗;而不輸入直接提交,會返回表單頁函數
WTForms提供了大量內置的字段類型,來便於咱們建立表單項,它們都放在」wtforms.fields」包下。下面,咱們建立一個用戶註冊表單類,並將經常使用的字段類型都包括在其中,爲了方便理解,描述就直接寫在註釋裏:ui
from wtforms.fields import (StringField, PasswordField, DateField, BooleanField, SelectField, SelectMultipleField, TextAreaField, RadioField, IntegerField, DecimalField, SubmitField) from wtforms.validators import DataRequired, Length, Email, EqualTo, NumberRange class RegisterForm(Form): # Text Field類型,文本輸入框,必填,用戶名長度爲4到25之間 username = StringField('Username', validators=[Length(min=4, max=25)]) # Text Field類型,文本輸入框,Email格式 email = StringField('Email Address', validators=[Email()]) # Text Field類型,密碼輸入框,必填,必須同confirm字段一致 password = PasswordField('Password', [ DataRequired(), EqualTo('confirm', message='Passwords must match') ]) # Text Field類型,密碼輸入框 confirm = PasswordField('Repeat Password') # Text Field類型,文本輸入框,必須輸入整型數值,範圍在16到70之間 age = IntegerField('Age', validators=[NumberRange(min=16, max=70)]) # Text Field類型,文本輸入框,必須輸入數值,顯示時保留一位小數 height = DecimalField('Height (Centimeter)', places=1) # Text Field類型,文本輸入框,必須輸入是"年-月-日"格式的日期 birthday = DateField('Birthday', format='%Y-%m-%d') # Radio Box類型,單選框,choices裏的內容會在ul標籤裏,裏面每一個項是(值,顯示名)對 gender = RadioField('Gender', choices=[('m', 'Male'), ('f', 'Female')], validators=[DataRequired()]) # Select類型,下拉單選框,choices裏的內容會在Option裏,裏面每一個項是(值,顯示名)對 job = SelectField('Job', choices=[ ('teacher', 'Teacher'), ('doctor', 'Doctor'), ('engineer', 'Engineer'), ('lawyer', 'Lawyer') ]) # Select類型,多選框,choices裏的內容會在Option裏,裏面每一個項是(值,顯示名)對 hobby = SelectMultipleField('Hobby', choices=[ ('swim', 'Swimming'), ('skate', 'Skating'), ('hike', 'Hiking') ]) # Text Area類型,段落輸入框 description = TextAreaField('Introduction of yourself') # Checkbox類型,加上default='checked'即默認是選上的 accept_terms = BooleanField('I accept the Terms of Use', default='checked', validators=[DataRequired()]) # Submit按鈕 submit = SubmitField('Register')
每一個字段類型的第一個參數都是顯示名,並且都接收」validator」參數來傳入驗證規則。上例的表單字段上,咱們用到了不少驗證規則,關於這部分,咱們會在下一小節介紹。對於時間日期字段,如」DateField」或」DateTimeField」,它們都有一個」format」參數來傳入可識別的日期格式;對於選擇框,如」RadioField」, 「SelectField」或」SelectMultipleField」,它們都有一個」choices」參數來傳入可選擇項,每一個項是一個」(值, 顯示名稱)」對,同時它們也有一個參數」coerce」參數來強制轉換選擇項值的類型,好比」coerce=int」。
接下來,讓咱們編寫模板,由於字段比較多,咱們先寫一個宏來渲染單個字段,並存放在模板文件」_field.html」中:
{% macro render_field(field) %} <tr> <td>{{ field.label }}</td> <td>{{ field(**kwargs)|safe }}</td> <td>{% if field.errors %} <ul class=errors> {% for error in field.errors %} <li>{{ error }}</li> {% endfor %} </ul> {% endif %} </td> </tr> {% endmacro %}
這個」render_field」宏用來渲染表格中的一個行,它有三個列,分別是字段顯示名,字段值,和錯誤信息(若是有錯誤的話)。而後,咱們寫」register.html」模板:
<!doctype html> <title>Registration Form Sample</title> <h1>User Registration</h1> {% from "_field.html" import render_field %} <form method="POST" action="{{ url_for('register') }}"> {{ form.hidden_tag() }} <table> {{ render_field(form.username) }} {{ render_field(form.email) }} {{ render_field(form.password) }} {{ render_field(form.confirm) }} {{ render_field(form.age) }} {{ render_field(form.height) }} {{ render_field(form.gender) }} {{ render_field(form.birthday) }} {{ render_field(form.job) }} {{ render_field(form.hobby) }} {{ render_field(form.description) }} {{ render_field(form.accept_terms) }} </table> {{ form.submit }} </form>
模板中導入」render_field」宏,並依次渲染用戶註冊表單裏的每個字段。最後,咱們寫個視圖函數來顯示這個表單:
@app.route('/register', methods=('GET', 'POST')) def register(): form = RegisterForm() if form.validate_on_submit(): flash('User "%s" registered successfully! Please login.' % form.username.data) login_form = LoginForm() return render_template('login.html', form=login_form) return render_template('register.html', form=form)
打開瀏覽器,訪問」/register」地址,你會看到這樣的表單頁面:
若是你什麼都不輸入,直接提交,錯誤信息將會在字段旁顯示:
這個頁面還很醜陋,你能夠經過CSS來美化它,本文就不介紹了。總之,你們已經被WTForms的強大感染到了吧!
上一節的例子中其實已經把大部分經常使用的驗證規則validator都用上了,WTForms一樣提供了大量內置的驗證規則,它們都放在」wtforms.validators」包下。這裏咱們就來列舉一下:
驗證規則 | 說明 |
---|---|
DataRequired | 驗證必填項 |
驗證郵件地址格式 | |
EqualTo | 驗證必須同另外一個字段值相同,它需傳入另外一個字段的名稱」fieldname」 |
Length | 驗證輸入字符串長度,它有兩個參數:」min」最小長度,」max」最大長度,缺省的話就不檢查 |
NumberRange | 驗證輸入數值的範圍,它有兩個參數:」min」最小值,」max」最大值,缺省的話就不檢查 |
URL | 驗證URL格式 |
IPAddress | 驗證IP地址格式,默認IPV4,你能夠傳入」ipv6=True」來驗證IPV6地址 |
MacAddress | 驗證Mac地址格式 |
AnyOf | 傳入一個列表做爲參數,驗證是否匹配列表中的任一值 |
NoneOf | 傳入一個列表做爲參數,驗證是否與列表中的全部值都不一樣 |
Regexp | 正則表達式驗證,需傳入一個正則表達式,它還有一個flags參數,若是你傳入」re.IGNORECASE」,就會忽略大小寫 |
全部的validator都有一個」message」參數,用來指定當驗證失敗時拋出的錯誤消息,不指定的話WTForms就會使用默認錯誤消息。
WTForms自己有一個」FileField」用來處理文件上傳功能,Flask-WTF擴展對其做了封裝,使得咱們能夠更方便的在Flask應用中實現文件上傳。如今就讓咱們來定義一個文件上傳的表單類:
from flask_wtf.file import FileField, FileAllowed, FileRequired class AttachForm(Form): attach = FileField('Your Attachment', validators=[ FileRequired(), FileAllowed(['jpg', 'png'], 'Images only!') ])
咱們引入」flask_wtf.file」包下的文件上傳框」FileField」,和兩個驗證規則」FileRequired」及」FileAllowed」。」FileRequired」驗證表單提交時必須有文件已被指定;」FileAllowed」驗證文件的類型,上例中只接收以」jpg」和」png」爲後綴的文件,若是不是會拋出錯誤消息」Images only!」。
模板文件很簡單,只要記得在」<form>」標籤里加上屬性’enctype=」multipart/form-data」‘便可:
<form method="POST" action="{{ url_for('upload') }}" enctype="multipart/form-data"> {{ form.hidden_tag() }} {{ form.attach.label }} {{ form.attach }} <input type="submit" value="Submit"> </form>
最後,寫上視圖函數:
from werkzeug import secure_filename @app.route('/upload', methods=('GET', 'POST')) def upload(): form = AttachForm() if form.validate_on_submit(): filename = secure_filename(form.attach.data.filename) form.attach.data.save('uploads/' + filename) return 'Upload successfully!'
「secure_filename」用來確保文件名安全,咱們在介紹Flask文件和流時有提到過。」form.attach.data」就能夠獲取文件的內容,它的」save()」方法能夠將內容保存到本地文件中去。上例中,咱們把文件保存在本地當前目錄下的」uploads」子目錄中。運行下這段程序,你將看到下圖這樣的表單,你能夠試着上傳一個文件。
因爲表單類是在Flask上下文環境外定義的,對於其字段顯示名的國際化,要使用」lazy_gettext」方法。好比:
from flask_wtf import Form from flask_babel import lazy_gettext from wtforms import StringField from wtforms.validators import DataRequired class MyForm(Form): user = StringField(lazy_gettext(u'Username'), validators=[DataRequired()])
從Flask-WTF版本0.13開始,」flask_wtf.Form」類被標爲」過期」了,取而代之的是」flask_wtf.FlaskForm」類。你們只須要將上面使用到Form的例子都改成FlaskForm就好了。