前言
我們在使用flask框架來搭建自己的博客,只要是設涉及到表單相關,必然會想起Flask-WTF與WTForms。對於flask初學者來說,比較容易混淆兩者。今天想來一一解釋兩者的用法。
Flask-WTF
基本了解
Flask-WTF是集成WTForms,並帶有 csrf 令牌的安全表單和全局的 csrf 保護的功能。
每次我們在建立表單所創建的類都是繼承與flask_wtf中的FlaskForm,而FlaskForm是繼承WTForms中forms。
用法:
1.創建基礎表單
例如,form.py:
class LoginForm(FlaskForm): username = StringField() password = PasswordField() remember_me = BooleanField(label='Keep me logged in')
2.CSRF保護
任何使用FlaskForm創建的表單發送請求,都會有CSRF的全部保護,在對應的template中HTML渲染表單時,可以加入form.csrf_token:
<form method="post"> {{ form.csrf_token }} </form>
但是如果模板中沒有表單,則可以使用一個隱藏的input標簽加入csrf_token。
<form method="post"> <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/> </form>
3.驗證表單
在視圖處理程序中驗證請求:
view.py
def login(): form = LoginForm() if form.validate_on_submit(): return redirect('/success') return render_template('login.html', form=form)
使用validate_on_submit
來檢查是否是一個 POST 請求並且請求是否有效。
4.文件上傳
Flask-WTF 提供 FileField
來處理文件上傳,它在表單提交后,自動從 flask.request.files
中抽取數據。FileField
的 data
屬性是一個 Werkzeug FileStorage 實例。
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 設置成 multipart/form-data,如下:
<form action="/upload/" method="POST" enctype="multipart/form-data"> .... </form>
5.驗證碼
Flask-WTF 通過 RecaptchaField 也提供對驗證碼的支持:
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 | 可選 驗證碼 API 服務器 |
RECAPTCHA_PARAMETERS | 可選 一個 JavaScript(api.js)參數的字典 |
RECAPTCHA_DATA_ATTRS | 可選 一個數據屬性項列表 https://developers.google.com/recaptcha/docs/display |
WTForms
基本了解
WTForms是一個Flask集成的框架,或者是說庫。用於處理瀏覽器表單提交的數據。它在Flask-WTF 的基礎上擴展並添加了一些隨手即得的精巧的幫助函數,這些函數將會使在 Flask 里使用表單更加有趣。
用法:
1.field字段
WTForms支持HTML字段:
字段類型 | 說明 |
---|---|
StringField | 文本字段, 相當於type類型為text的input標簽 |
TextAreaField | 多行文本字段 |
PasswordField | 密碼文本字段 |
HiddenField | 隱藏文本字段 |
DateField | 文本字段, 值為datetime.date格式 |
DateTimeField | 文本字段, 值為datetime.datetime格式 |
IntegerField | 文本字段, 值為整數 |
DecimalField | 文本字段, 值為decimal.Decimal |
FloatField | 文本字段, 值為浮點數 |
BooleanField | 復選框, 值為True 和 False |
RadioField | 一組單選框 |
SelectField | 下拉列表 |
SelectMultipleField | 下拉列表, 可選擇多個值 |
FileField | 文件上傳字段 |
SubmitField | 表單提交按鈕 |
FormFiled | 把表單作為字段嵌入另一個表單 |
FieldList | 子組指定類型的字段 |
2.Validators驗證器
WTForms可以支持很多表單的驗證函數:
驗證函數 | 說明 |
---|---|
驗證是電子郵件地址 | |
EqualTo | 比較兩個字段的值; 常用於要求輸入兩次密鑰進行確認的情況 |
IPAddress | 驗證IPv4網絡地址 |
Length | 驗證輸入字符串的長度 |
NumberRange | 驗證輸入的值在數字范圍內 |
Optional | 無輸入值時跳過其它驗證函數 |
DataRequired | 確保字段中有數據 |
Regexp | 使用正則表達式驗證輸入值 |
URL | 驗證url |
AnyOf | 確保輸入值在可選值列表中 |
NoneOf | 確保輸入值不在可選列表中 |
3.自定義Validators驗證器
第一種: in-line validator(內聯驗證器)
也就是自定義一個驗證函數,在定義表單類的時候,在對應的字段中加入該函數進行認證。下面的my_length_check
函數就是用於判name
字段長度不能超過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])
第二種:通用且可重用的驗證函數
一般是以validate
開頭,加上下划線再加上對應的field字段(validate_filed),瀏覽器在提交表單數據時,會自動識別對應字段所有的驗證器,然后執行驗證器進行判斷。
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')
第三種:比較高級的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組件
下面可以以登錄界面為實例:
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'} )
總結
其實flask表單這一部分我們都是使用Flask-WTF與WTForms來進行實現,比如說做一下簡單的系統登錄界面、注冊界面等等,可以利用它們來做一些小demo,你就可以深入理解它的原理並且可以強化flask的基礎。如果不懂的,也希望大家可以參考我最近做的開源項目SimpleBlog,里面大量應用到Flask-WTF與WTForms。
參考鏈接:
1.https://wtforms.readthedocs.io/en/stable/
2.https://flask-wtf.readthedocs.io/en/stable/
作者:BourneKing
鏈接:https://www.jianshu.com/p/7e16877757f8
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。