前言
我們?cè)谑褂胒lask框架來搭建自己的博客淮腾,只要是設(shè)涉及到表單相關(guān)糟需,必然會(huì)想起Flask-WTF與WTForms。對(duì)于flask初學(xué)者來說来破,比較容易混淆兩者篮灼。今天想來一一解釋兩者的用法。
Flask-WTF
基本了解
Flask-WTF是集成WTForms徘禁,并帶有 csrf 令牌的安全表單和全局的 csrf 保護(hù)的功能诅诱。
每次我們?cè)诮⒈韱嗡鶆?chuàng)建的類都是繼承與flask_wtf中的FlaskForm,而FlaskForm是繼承WTForms中forms送朱。
用法:
1.創(chuàng)建基礎(chǔ)表單
例如娘荡,form.py:
class LoginForm(FlaskForm):
username = StringField()
password = PasswordField()
remember_me = BooleanField(label='Keep me logged in')
2.CSRF保護(hù)
任何使用FlaskForm創(chuàng)建的表單發(fā)送請(qǐng)求,都會(huì)有CSRF的全部保護(hù)驶沼,在對(duì)應(yīng)的template中HTML渲染表單時(shí)炮沐,可以加入form.csrf_token:
<form method="post">
{{ form.csrf_token }}
</form>
但是如果模板中沒有表單,則可以使用一個(gè)隱藏的input標(biāo)簽加入csrf_token回怜。
<form method="post">
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
</form>
3.驗(yàn)證表單
在視圖處理程序中驗(yàn)證請(qǐng)求:
view.py
def login():
form = LoginForm()
if form.validate_on_submit():
return redirect('/success')
return render_template('login.html', form=form)
使用validate_on_submit
來檢查是否是一個(gè) POST 請(qǐng)求并且請(qǐng)求是否有效大年。
4.文件上傳
Flask-WTF 提供 FileField
來處理文件上傳,它在表單提交后,自動(dòng)從 flask.request.files
中抽取數(shù)據(jù)翔试。FileField
的 data
屬性是一個(gè) Werkzeug FileStorage 實(shí)例轻要。
from werkzeug import secure_filename
from flask_wtf.file import FileField
class PhotoForm(Form):
photo = FileField('Your photo')
@app.route('/upload/', methods=('GET', 'POST'))
def upload():
form = PhotoForm()
if form.validate_on_submit():
filename = secure_filename(form.photo.data.filename)
form.photo.data.save('uploads/' + filename)
else:
filename = None
return render_template('upload.html', form=form, filename=filename)
注意:在 HTML 表單的 enctype 設(shè)置成 multipart/form-data,如下:
<form action="/upload/" method="POST" enctype="multipart/form-data">
....
</form>
5.驗(yàn)證碼
Flask-WTF 通過 RecaptchaField 也提供對(duì)驗(yàn)證碼的支持:
from flask_wtf import Form, RecaptchaField
from wtforms import TextField
class SignupForm(Form):
username = TextField('Username')
recaptcha = RecaptchaField()
還需要配置一下信息:
字段 | 配置 |
---|---|
RECAPTCHA_PUBLIC_KEY | 必須 公鑰 |
RECAPTCHA_PRIVATE_KEY | 必須 私鑰 |
RECAPTCHA_API_SERVER | 可選 驗(yàn)證碼 API 服務(wù)器 |
RECAPTCHA_PARAMETERS | 可選 一個(gè) JavaScript(api.js)參數(shù)的字典 |
RECAPTCHA_DATA_ATTRS | 可選 一個(gè)數(shù)據(jù)屬性項(xiàng)列表 https://developers.google.com/recaptcha/docs/display |
WTForms
基本了解
WTForms是一個(gè)Flask集成的框架垦缅,或者是說庫冲泥。用于處理瀏覽器表單提交的數(shù)據(jù)。它在Flask-WTF 的基礎(chǔ)上擴(kuò)展并添加了一些隨手即得的精巧的幫助函數(shù)壁涎,這些函數(shù)將會(huì)使在 Flask 里使用表單更加有趣凡恍。
用法:
1.field字段
WTForms支持HTML字段:
字段類型 | 說明 |
---|---|
StringField | 文本字段, 相當(dāng)于type類型為text的input標(biāo)簽 |
TextAreaField | 多行文本字段 |
PasswordField | 密碼文本字段 |
HiddenField | 隱藏文本字段 |
DateField | 文本字段怔球, 值為datetime.date格式 |
DateTimeField | 文本字段嚼酝, 值為datetime.datetime格式 |
IntegerField | 文本字段, 值為整數(shù) |
DecimalField | 文本字段竟坛, 值為decimal.Decimal |
FloatField | 文本字段革半, 值為浮點(diǎn)數(shù) |
BooleanField | 復(fù)選框, 值為True 和 False |
RadioField | 一組單選框 |
SelectField | 下拉列表 |
SelectMultipleField | 下拉列表流码, 可選擇多個(gè)值 |
FileField | 文件上傳字段 |
SubmitField | 表單提交按鈕 |
FormFiled | 把表單作為字段嵌入另一個(gè)表單 |
FieldList | 子組指定類型的字段 |
2.Validators驗(yàn)證器
WTForms可以支持很多表單的驗(yàn)證函數(shù):
驗(yàn)證函數(shù) | 說明 |
---|---|
驗(yàn)證是電子郵件地址 | |
EqualTo | 比較兩個(gè)字段的值; 常用于要求輸入兩次密鑰進(jìn)行確認(rèn)的情況 |
IPAddress | 驗(yàn)證IPv4網(wǎng)絡(luò)地址 |
Length | 驗(yàn)證輸入字符串的長(zhǎng)度 |
NumberRange | 驗(yàn)證輸入的值在數(shù)字范圍內(nèi) |
Optional | 無輸入值時(shí)跳過其它驗(yàn)證函數(shù) |
DataRequired | 確保字段中有數(shù)據(jù) |
Regexp | 使用正則表達(dá)式驗(yàn)證輸入值 |
URL | 驗(yàn)證url |
AnyOf | 確保輸入值在可選值列表中 |
NoneOf | 確保輸入值不在可選列表中 |
3.自定義Validators驗(yàn)證器
第一種: in-line validator(內(nèi)聯(lián)驗(yàn)證器)
也就是自定義一個(gè)驗(yàn)證函數(shù)延刘,在定義表單類的時(shí)候漫试,在對(duì)應(yīng)的字段中加入該函數(shù)進(jìn)行認(rèn)證。下面的my_length_check
函數(shù)就是用于判name
字段長(zhǎng)度不能超過50.
def my_length_check(form, field):
if len(field.data) > 50:
raise ValidationError('Field must be less than 50 characters')
class MyForm(Form):
name = StringField('Name', [InputRequired(), my_length_check])
第二種:通用且可重用的驗(yàn)證函數(shù)
一般是以validate
開頭碘赖,加上下劃線再加上對(duì)應(yīng)的field字段(validate_filed)驾荣,瀏覽器在提交表單數(shù)據(jù)時(shí),會(huì)自動(dòng)識(shí)別對(duì)應(yīng)字段所有的驗(yàn)證器普泡,然后執(zhí)行驗(yàn)證器進(jìn)行判斷播掷。
class RegistrationForm(FlaskForm):
email = StringField('Email', validators=[DataRequired(), Length(1, 60), Email()])
username = StringField('Username', validators=[DataRequired(), Length(1, 60),
Regexp('^[A-Za-z][A-Za-z0-9_.]*$', 0, 'username must have only letters, numbers dots or underscores')])
password = PasswordField('Password', validators=[DataRequired(), EqualTo('password2', message='password must match')])
password2 = PasswordField('Confirm password', validators=[DataRequired()])
def validate_email(self, field):
if User.objects.filter(email=field.data).count() > 0:
raise ValidationError('Email already registered')
def validate_username(self, field):
if User.objects.filter(username=field.data).count() > 0:
raise ValidationError('Username has exist')
第三種:比較高級(jí)的validators
class Length(object):
def __init__(self, min=-1, max=-1, message=None):
self.min = min
self.max = max
if not message:
message = u'Field must be between %i and %i characters long.' % (min, max)
self.message = message
def __call__(self, form, field):
l = field.data and len(field.data) or 0
if l < self.min or self.max != -1 and l > self.max:
raise ValidationError(self.message)
length = Length
4.Widget組件
下面可以以登錄界面為實(shí)例:
login.py
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from flask import Flask, render_template, request, redirect
from wtforms import Form
from wtforms import validators
from wtforms import widgets
class LoginForm(Form):
name = simple.StringField(
label='用戶名',
validators=[
validators.DataRequired(message='用戶名不能為空.'),
],
widget=widgets.TextInput(),
render_kw={'class': 'form-control'}
)
pwd = simple.PasswordField(
label='密碼',
validators=[
validators.DataRequired(message='密碼不能為空.'),
],
widget=widgets.PasswordInput(),
render_kw={'class': 'form-control'}
)
總結(jié)
其實(shí)flask表單這一部分我們都是使用Flask-WTF與WTForms來進(jìn)行實(shí)現(xiàn),比如說做一下簡(jiǎn)單的系統(tǒng)登錄界面撼班、注冊(cè)界面等等歧匈,可以利用它們來做一些小demo,你就可以深入理解它的原理并且可以強(qiáng)化flask的基礎(chǔ)砰嘁。如果不懂的件炉,也希望大家可以參考我最近做的開源項(xiàng)目SimpleBlog,里面大量應(yīng)用到Flask-WTF與WTForms。
參考鏈接:
1.https://wtforms.readthedocs.io/en/stable/
2.https://flask-wtf.readthedocs.io/en/stable/