Flask入門 表單Flask-wtf form原生 Bootstrap渲染(七)
(1) 原生的表單
模板頁面,form表單form.html
<form action="{{ url_for(‘/check/‘) }}" method=‘post‘>
<p>用戶名: <input type=‘text‘ name=‘username‘></p>
<p>密碼: <input type=‘password‘ name=‘userpass‘></p>
<p><input type=‘submit‘ value=‘submit‘></p>
</ form>
在manage.py中
#原生表單
@app.route(‘/form‘)
def form():
return render_template(‘form.html‘)
#獲取原生表單提交的數據
@app.route(‘/check‘,method=[‘POST‘])
def check():
print(request.form.get(‘userpass‘))
print(request.form.get(‘username‘))
return ‘提交數據‘
#註: 第一個form函數僅僅是跳轉頁面作用,比較浪費因此我們可以合並一下
在manage.py中將路由函數合並
@app.route(‘/form‘)
def form():
if request.method == ‘POST‘:
print(request.form.get(‘userpass‘))
print(request.form.get(‘username‘))
return render_template(‘/form.html‘)
(2) Flask-wtf表單
說明 : 是一個用於表單處理,校驗並提供csrf驗證的功能的擴展庫
安裝 :
sudo pip3 install flask-wtf
作用: Flask-wtf能保護所有表單免受跨站請求偽造的攻擊(Cross-Site Request Forgery,CSRF),惡意網站會把請求發送到被攻擊者登錄的其他網站就會引起CSRF攻擊,因此我們需要實現CSRF保護機制,Flask-wtf采用的做法是為程序設置一個秘鑰,Flask-WTF 使用這個密鑰生成加密令牌,再用令牌驗證請求中表單數據的真偽。
app = Flask(__name__)
app.config[‘SECRET_KEY‘] = ‘sadad131[]‘
#采用字典的方式存儲框架,擴展和程序本身的配置變量,一般秘鑰不直接寫入代碼,放在環境變量增加安全性.
flask-wtf一般自定義的表單類都是繼承自Form類或者其子類,一般有表單類,驗證器類
- 表單類主要有以下幾種:
字段類型 | 字段說明 |
---|---|
StringField | 普通文本字段 |
TextAreaField | 多行文本字段 |
SubmitField | 提交 |
PasswordField | 密碼字段 |
HiddenField | 隱藏文本字段 |
DateField | 日期字段 datetime.date(year=2018,month=2,day=20) 2018-02-20 |
DateTimeFiled | 時間字段 datetime.datetime(year=2018,month=2,day=20) 2018-02-20 00:00:00 |
IntegerField | 文本字段,值為整數 |
FloatField | 文本字段,值是浮點數 |
DecimalField | 文本字段,值為 decimal.Decimal |
BooleanField | 復選框,值為 True 和 False |
RadioField | 一組單選框 choices = [(‘w‘,‘女‘),(‘m‘,‘男‘)] 參數1作為傳遞,參數2位顯示值 |
SelectField | 下拉列表 choices參數確定了下拉選項, 是一個tuple組成的列表 (同上) |
SelectMultipleField | 下拉列表,可選擇多個值 |
FileField | 文件上傳字段 |
FormField | 把表單作為字段嵌入另一個表單 |
? Validator是驗證函數,把一個字段綁定驗證函數之後,flask在接受表單之前會做一個驗證 , 如果驗證成功才會接收數據。驗證函數Validator如下,
2 驗證器一般有以下幾種:
- 基本上每一個validator都有message參數,指出當輸入數據不符合validator要求時顯示什麽信息
驗證器函數 | 說明 |
---|---|
DataRequired/Required | 代表內容是必填項 DataRequired(message=‘用戶信息不能為空‘) |
驗證電子郵件地址,要求正則模式 : ^.+@([^.@][^@]+)$ |
|
EqualTo | 比較兩個字段的值,常用於確認密碼情況 EqualTo(‘要確認字段名‘,message=‘xxx‘) |
IPAddress | 驗證IPV4網絡地址 參數默認ipv4=True,ipv6=False |
Length | 驗證輸入字符串的長度 參數類型是字符串Length(min=6,max=30,message=‘個人信息的簡介6-30個字‘) |
NumberRange | 驗證輸入的值在數字範圍內NumberRange(min=6,max=90,message=‘年齡為6-90歲‘) |
Optional | 無輸入值時跳過其他驗證函數 |
Regexp | 使用正則表達式驗證輸入值 參數regex=‘正則模式‘ |
URL | 驗證 URL URL(message=‘請輸入正確的url地址‘)] 正則模式是^[a-z]+://(?P<host>[^/:]+)(?P<port>:[0-9]+)?(?P<path>\/.*)?$ |
AnyOf | 確保輸入值在可選值列表中 |
NoneOf | 確保輸入值不在可選值列表中 |
實例wtf表單
模板文件 form.html
<form action="{{ url_for(‘wtf_form‘) }}" method=‘post‘>
{{ form.csrf_token }} #進入csrf驗證
<p>{{ form.username.label }}{{ form.username(style=‘color:red‘,placeholder=‘請輸入用戶名‘) }}{{ form.username.errors }}</p>
<p>{{ form.userpass.label }}{{ form.userpass() }}{{ form.userpass.errors }}</p>
<p>{{ form.submit() }}</p>
</form>
#通過form.字段名獲取對應字段屬性 form.字段名(修飾符)
manage.py文件中
from flask import Flask,render_template,request
from flask_wtf import FlaskForm #導入繼承父類
from wtforms import StringField,PasswordField,SubmitField
from wtforms.validators import Length,DataRequired
class Login(FlaskForm): #繼承自FlaskForm類
username = StringField(‘用戶名‘,validators=[Length(min=6,max=12,message=‘用戶名長度為6~12位‘),DataRequired(message=‘用戶名不能為空‘)])
userpass = PasswordField(‘密碼‘,validators=[Length(min=6,max=12,message=‘密碼長度為6~12位‘),DataRequired(message=‘密碼不能為空‘)])
submit = SubmitField(‘登錄‘)
@app.route(‘/wtf_form‘,methods=[‘GET‘,‘POST‘])
def wtf_form():
form = Login() #實例化form對象
if request.method == ‘POST‘:
if form.validate_on_submit(): #數據正確 並且驗證csrf通過
print(request.form.get(‘userpass‘))
print(request.form.get(‘username‘))
return ‘數據提交成功‘
return render_template(‘wtf_form.html‘,form=form)
#註:
#1 methods 參數告訴Flask在URL映射中把這個視圖函數註冊為GET和POST請求的處理程序,默認GET
#2 采用post請求可以通過對象很輕松訪問,GET 請求沒有主體,提交的數據以查詢字符串的形式附加到URL中
#3 validate_on_submit() 會調用username 字段上附屬的 DataRequired() 驗證函數。
註意: 1 form.validate_on_submit() 只有在數據正確 並且驗證csrf通過 返回True
? 2 {{ form.csrf_token }} 進入表單 csrf 驗證
(3) 使用bootstrap快速渲染
安裝
pip3 install flask-bootstrap
視圖函數:導入與實例
from flask_bootstrap import Bootstrap #導入
bootstrap = Bootstrap(app) #綁定bootstrap與該項目app的關系
導入 :基本用到的模板為 base.html 繼承基類 和wtf.html 導入宏
{% import ‘bootstrap/wtf.html‘ as wtf %} #導入重命名為wtf
{{ wtf.quick_form(form,url_for(‘index‘)) }} #訪問宏wtf.quick_form(‘數據‘,路由)
{{ wtf.quick_form(form) }}
? 可以使用 Bootstrap 中預先定義好的表單樣式渲染整個 Flask-WTF 表單。導入模板中的bootstrap/wtf.html 元素。定義了一個使用 Bootstrap 渲染 Falsk-WTF 表單對象的輔助函數。 wtf.quick_form() 函數的參數為 Flask-WTF 表單對象,使用 Bootstrap 的默認樣式渲染傳入的表單。
index.html
{ % extends "base.html" % } #繼承base.html,必須寫在最前面
{ % import "bootstrap/wtf.html" as wtf % } #重命名wtf
{ % block title % }首頁{ % endblock % }
{ % block page_content % } #定義內容
<div class="page-header">
<h1>Hello, { % if username % }{{ username }}{ % else % }Stranger{ % endif % }!</h1>
</div>
{{ wtf.quick_form(form) }} #傳入表單對象
{ % endblock % }
(4) 重定向和用戶會話(Post/重定向/Get 模式)
基於Web程序把POST請求作為瀏覽器發送的最後一個請求,這種需求的實現方式是,使用重定向作為 POST 請求的響應,而不是使用常規響應。但是請求結束之後form.username.data接受的數據為用戶輸入的名字也就丟失了.因此我們采取將數據存儲放在用戶會話session中.
from flask import Flask,render_template,session,redirect,url_for
@app.route(‘/‘,methods=[‘GET‘,‘POST‘])
def index():
form = Login()
if form.validate_on_submit(): #判斷request是個帶POST數據,且數據符合表單定義要求
session[‘username‘] = form.username.data #將username保存到session
return redirect(url_for(‘index‘)) #重定向到‘index視圖函數路由‘
return render_template(‘index.html‘,form=form,name=session.get[‘username‘])
#註: <表單對象名>.<Field名稱>.data 可以訪問POST請求對應字段數據
(5) Flash消息
Flask的核心特性Flash實現: 為了解決用戶提交了有一項錯誤的登錄表單後,服務器發回的響應重新渲染了登錄表單,並在表單上面顯示一個消息,提示用戶用戶名或密碼錯誤。常常用於表單信息提示.
flash()
作用是每次調用flash()都會觸發一個消息所以可能有多個消息在排隊等待顯示。
get_flashed_messages()
函數獲取傳入的消息 其實就是一個列表, 獲取的消息在下次調用時不會再次返回,因此 Flash 消息只顯示一次,然後就消失了。
使用
from flask import flask,get_flashed_messages
@app.route(‘/register/‘,method=[‘GET‘,‘POST‘])
def register():
form = Register()
if form.validate_on_submit():
flash(‘註冊成功‘)
return redirect(url_for(‘index‘))
return render_template(‘form.html‘,form=form)
在模板中獲取
{% for message in get_flashed_messages() %}
<div class="alert alert-success alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span
aria-hidden="true">×</span></button>
<strong>success!</strong>{{ message }}
</div>
{% endfor %}
flash使用當然不僅僅限於單一消息的傳遞,flash的源碼定義為 :
def flash(message, category=‘message‘):
因此可以看到不僅能傳遞消息message
還能將傳遞的消息進行類別category
選擇
get_flashed_messages同樣有接受信息類別的屬性with_categories=
設置為True
def get_flashed_messages(with_categories=False, category_filter=[]):
例如
if content.split(‘\n‘) <= 2:
flash(message=u‘警告‘,category=‘warning‘)
elif content.split(‘\n‘) >= 5:
flash(message=u‘不允許的操作‘,category=‘danger‘)
{% block content %}
{% for category,message in get_flashed_message(with_category=True) %}
<div class="alert alert-{{ category }} alert-dismissable">
<button type="button" class="close" data-dismiss="alert">&tims;</button>
{{ message }}
</div>
{% endfor %}
{% endblock %}
#按照分級信息彈出不同的顯示框
Flask入門 表單Flask-wtf form原生 Bootstrap渲染(七)