title: flask學習筆記
subtitle: 3. flask Web表單
date: 2018-12-14 10:17:28
---
Web表單
HTML表單是用戶和web站點或應用程序之間交互的主要內容之一。它們允許用戶將數據發送到web站點。大多數情況下,數據被發送到web服務器,但是web頁面也可以自己攔截它并使用它。
HTML表單是由一個或多個小部件組成的。這些小部件可以是文本字段(單行或多行)、選擇框、按鈕、復選框或單選按鈕。大多數情況下,這些小部件與描述其目的的標簽配對——正確實現的標簽能夠清楚地指示視力正常的用戶和盲人用戶輸入表單所需的內容。
HTML 表單-示例:
Flask-WTF插件
Flask-WTF插件來處理本應用中的Web表單,它對WTForms進行了淺層次的封裝以便和Flask完美結合
配置
最基本的解決方案是使用app.config對象,它是一個類似字典的對象,可以將配置以鍵值的方式存儲其中。松耦和,配置和應用代碼分開放置
Flask及其一些擴展使用密鑰的值作為加密密鑰,用于生成簽名或令牌。Flask-WTF插件使用它來保護網頁表單免受名為Cross-Site Request Forgery或CSRF(發音為“seasurf”)的惡意攻擊。
密鑰被定義成由or運算符連接兩個項的表達式。第一個項查找環境變量SECRET_KEY的值,第二個項是一個硬編碼的字符串。這種首先檢查環境變量中是否存在這個配置,找不到的情況下就使用硬編碼字符串的配置變量的模式你將會反復看到。在開發階段,安全性要求較低,因此可以直接使用硬編碼字符串。但是,當應用部署到生產服務器上的時候,我將設置一個獨一無二且難以揣摩的環境變量,這樣,服務器就擁有了一個別人未知的安全密鑰了。
config.py:
import osclass Config(object):SECRET_KEY = os.environ.get('SECRET_KEY') or 'you-will-never-guess'app/__init__.py:
from flask import Flask
from config import Configapp = Flask(__name__)
app.config.from_object(Config)from app import routes
配置2
CSRF_ENABLED 配置是為了激活 跨站點請求偽造 保護。在大多數情況下,需要激活該配置使得應用程序更安全些。
SECRET_KEY 配置僅僅當 CSRF 激活的時候才需要,它是用來建立一個加密的令牌,用于驗證一個表單。當你編寫自己的應用程序的時候,請務必設置很難被猜測到密鑰。
config.py:
CSRF_ENABLED = True
SECRET_KEY = 'you-will-never-guess'app/__init__.py:
from flask import Flaskapp = Flask(__name__)
app.config.from_object('config')from app import views
Flask Web表單
Flask Web表單由三部分構成,用戶登錄表單,表單模板,表單視圖。用戶登錄表單定義HTML網頁上的數據。表單模板將表單添加到HTML模板以便渲染到網頁。表單視圖創建form實例,并將其傳入渲染模板的函數中,然后用*/login* URL來關聯它。
用戶登錄表單
# @File : forms.py
# @Software: PyCharm# from flask_wtf import FlaskForm
# from wtforms import StringField, BooleanField
# from wtforms.validators import DataRequired
#
#
# class LoginForm(FlaskForm):
# openid = StringField('openid', validators=[DataRequired()])
# remember_me = BooleanField('remember_me', default=False)from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField
from wtforms.validators import DataRequiredclass LoginForm(FlaskForm):username = StringField('Username', validators=[DataRequired()])password = PasswordField('Password', validators=[DataRequired()])remember_me = BooleanField('Remember Me')submit = SubmitField('Sign In')
表單模板(.html文件)
HTML<\form>元素被用作Web表單的容器。 表單的action屬性告訴瀏覽器在提交用戶在表單中輸入的信息時應該請求的URL。 當action設置為空字符串時,表單將被提交給當前地址欄中的URL,即當前頁面。 method屬性指定了將表單提交給服務器時應該使用的HTTP請求方法。 默認情況下是用GET請求發送,但幾乎在所有情況下,使用POST請求會提供更好的用戶體驗,因為這種類型的請求可以在請求的主體中提交表單數據, GET請求將表單字段添加到URL,會使瀏覽器地址欄變得混亂。
<!-- extend from base layout -->
{% extends "base.html" %}{% block content %}
<h1>Sign In</h1>
{#<form action="" method="post" name="login">#}
{# {{form.hidden_tag()}}#}
{# <p>#}
{# Please enter your OpenID:<br>#}
{# {{form.openid(size=80)}}<br>#}
{# </p>#}
{# <p>{{form.remember_me}} Remember Me</p>#}
{# <p><input type="submit" value="Sign In"></p>#}
{#</form>#}<form action="" method="post" novalidate>{{ form.hidden_tag() }}<p>{{ form.username.label }}<br>{{ form.username(size=32) }}</p><p>{{ form.password.label }}<br>{{ form.password(size=32) }}</p><p>{{ form.remember_me() }} {{ form.remember_me.label }}</p><p>{{ form.submit() }}</p></form>
{% endblock %}
表單視圖
form.validate_on_submit()實例方法會執行form校驗的工作。當瀏覽器發起GET請求的時候,它返回False,這樣視圖函數就會跳過if塊中的代碼,直接轉到視圖函數的最后一句來渲染模板。
當用戶在瀏覽器點擊提交按鈕后,瀏覽器會發送POST請求。form.validate_on_submit()就會獲取到所有的數據,運行字段各自的驗證器,全部通過之后就會返回True,這表示數據有效。不過,一旦有任意一個字段未通過驗證,這個實例方法就會返回False,引發類似GET請求那樣的表單的渲染并返回給用戶。稍后我會在添加代碼以實現在驗證失敗的時候顯示一條錯誤消息。
當form.validate_on_submit()返回True時,登錄視圖函數調用從Flask導入的兩個新函數。 flash()函數是向用戶顯示消息的有效途徑。 許多應用使用這個技術來讓用戶知道某個動作是否成功。我將使用這種機制作為臨時解決方案,因為我沒有基礎架構來真正地登錄用戶。 顯示一條消息來確認應用已經收到登錄認證憑據,我認為對當前來說已經足夠了。
登錄視圖函數中使用的第二個新函數是redirect()。這個函數指引瀏覽器自動重定向到它的參數所關聯的URL。當前視圖函數使用它將用戶重定向到應用的主頁。
# @File : views.py
# @Software: PyCharm# from flask import render_template
# render_template函數需要傳入模板名以及一些模板變量列表,返回一個所有變量被替換的渲染的模板。
from app import app
from flask import render_template, flash, redirect
from .forms import LoginForm# index view function suppressed for brevity
@app.route('/login', methods=['GET', 'POST'])
def login():form = LoginForm()# if form.validate_on_submit():# flash('Login requested for OpenID="' + form.openid.data + '", remember_me=' + str(form.remember_me.data))# return redirect('/index')# return render_template('login.html', title='Sign In', form=form)if form.validate_on_submit():flash('Login requested for user {}, remember_me={}'.format(form.username.data, form.remember_me.data))return redirect('/index')return render_template('login.html', title='Sign In', form=form)