欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

在Python的Flask框架中構(gòu)建Web表單的教程

 更新時(shí)間:2016年06月04日 14:59:28   作者:ipython  
Flask框架中自帶一個(gè)Form表單類,通過它的子類來實(shí)現(xiàn)表單將相當(dāng)愜意,這里就為大家?guī)鞵ython的Flask框架中構(gòu)建Web表單的教程,需要的朋友可以參考下

盡管Flask的request對象提供的支持足以處理web表單,但依然有許多任務(wù)會(huì)變得單調(diào)且重復(fù)。表單的HTML代碼生成和驗(yàn)證提交的表單數(shù)據(jù)就是兩個(gè)很好的例子。

Flask-WTF擴(kuò)展使得處理web表單能獲得更愉快的體驗(yàn)。該擴(kuò)展是一個(gè)封裝了與框架無關(guān)的WTForms包的Flask集成。

Flask-WTF和它的依賴集可以通過pip來安裝:

(venv) $ pip install flask-wtf

1、跨站請求偽造(CSRF)保護(hù)
默認(rèn)情況下,F(xiàn)lask-WTF保護(hù)各種形式對跨站請求偽造(CSRF)攻擊。一個(gè)CSRF攻擊發(fā)生在一個(gè)惡意網(wǎng)站發(fā)送請求給受害者登錄的其他網(wǎng)站。

為了實(shí)現(xiàn)CSRF保護(hù),F(xiàn)lask-WTF需要應(yīng)用程序去配置一個(gè)加密密鑰。Flask-WTF使用這個(gè)密鑰去生成加密令牌用于驗(yàn)證請求表單數(shù)據(jù)的真實(shí)性。下面將展示如何配置加密密鑰。

示例hello.py:Flask-WTF配置

app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'

app.config字典通常是框架、擴(kuò)展或應(yīng)用程序自身存放配置變量的地方,可以使用標(biāo)準(zhǔn)字典語法添加配置值到app.config中。配置對象提供方法來從文件或環(huán)境導(dǎo)入配置值。

SECRET_KEY配置變量作為Flask和一些第三方擴(kuò)展的通用加密密鑰。加密的強(qiáng)度取決于這個(gè)變量的值。給你構(gòu)建的每個(gè)應(yīng)用程序選擇不同的密鑰,并確保這個(gè)字符串不被其他任何人知道。

注:為了提高安全性,密鑰應(yīng)該存儲(chǔ)在一個(gè)環(huán)境變量中,而不是嵌入到代碼中。這個(gè)會(huì)在第7章中描述。

2、表單類
使用Flask-WTF時(shí),每個(gè)web表單是由繼承自Form類的子類來展現(xiàn)的。該類在表單中定義了一組表單域,每個(gè)都表示為一個(gè)對象。每個(gè)表單域都可以連接到一個(gè)或多個(gè)validators;validators是一個(gè)用于檢查用戶提交的輸入是否合法的函數(shù)。

下面的示例展示了一個(gè)擁有文本框和提交按鈕的簡單web表單。

示例hello.py:表單類定義

from flask.ext.wtf import Form
from wtforms import StringField, SubmitField 
from wtforms.validators import Required

class NameForm(Form):
 name = StringField('What is your name?', validators=[Required()]) 
 submit = SubmitField('Submit')

表單中的域被定義為類的變量,且每個(gè)類的變量都指定一個(gè)表單域類型對象。在上一個(gè)示例中,NameForm表單有一個(gè)name文本框和submit提交按鈕。StringField類表示一個(gè)type="text"屬性的<input>標(biāo)簽。SubmitField類表示一個(gè)type="submit"屬性的<input>標(biāo)簽。表單域構(gòu)造函數(shù)的第一個(gè)參數(shù)是一個(gè)label,在渲染表單到HTML時(shí)會(huì)使用。

StringField構(gòu)造函數(shù)包含可選參數(shù)validators,它定義了一組檢查來驗(yàn)證用戶提交的數(shù)據(jù)。Required()驗(yàn)證確保提交的表單域不為空。

注:Flask-WTF擴(kuò)展定義了表單基類,所以它從flask.ext.wtf導(dǎo)入。表單域、驗(yàn)證都是直接從WTForms包中導(dǎo)入。
下面的表格展示了一組WTForms支持的標(biāo)準(zhǔn)表單域。
表格WTForms標(biāo)準(zhǔn)HTML表單域

201664144842266.png (407×469)

下面則展示了一組WTForms內(nèi)建驗(yàn)證。
 WTForms驗(yàn)證

201664144936162.png (494×337)

3、HTML渲染的表單
表單域是可調(diào)用的,調(diào)用時(shí)從模板渲染它們到HTML。假設(shè)視圖函數(shù)傳遞一個(gè)參數(shù)名為form的NameForm實(shí)例給模板,模板就會(huì)生成一個(gè)簡單的HTML表單,如下所示:

<form method="POST">
 {{ form.name.label }} {{ form.name() }} 
 {{ form.submit() }}
</form>

當(dāng)然,結(jié)果是什么都沒有。為了改變表單的外觀顯示,任何發(fā)送給該表單域的參數(shù)會(huì)被轉(zhuǎn)換為HTML表單域?qū)傩?;例如,你可以給定表單域id或class屬性,然后定義CSS樣式:

<form method="POST">
 {{ form.name.label }} {{ form.name(id='my-text-field') }} 
 {{ form.submit() }}
</form>

即使有HTML屬性,努力用這種方式渲染表單是非常重要的,所以最好是盡可能的使用Bootstrap自帶的一系列表單樣式。Flask-Bootstrap使用Bootstrap的預(yù)定義表單樣式來提供高級(jí)的幫助函數(shù)來渲染整個(gè)Flask-WTF表單,這些操作都只需要一個(gè)調(diào)用即可完成。使用Flask-Bootstrap,上一個(gè)表單可以像下面這樣來渲染:

{% import "bootstrap/wtf.html" as wtf %}
{{ wtf.quick_form(form) }}

import指令和常規(guī)的Python腳本一樣的作用并且允許模板元素被導(dǎo)入并在許多模板中使用。被導(dǎo)入的bootstrap/wtf.html文件,定義了幫助函數(shù)使用Bootstrap來渲染Flask-WTF表單。wtf.quick_form()函數(shù)傳入Flask-WTF表單對象并使用默認(rèn)Bootstrap樣式渲染它。示例4-3展示了完整的hello.py模板。

示例 templates/index.html:使用Flask-WTF和Flask-Bootstrap渲染表單

{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf %}

{% block title %}Flasky{% endblock %}

{% block page_content %}


<div class="page-header">
 <h1>Hello, {% if name %}{{ name }}{% else %}Stranger{% endif %}!</h1>
</div>


{{ wtf.quick_form(form) }}
{% endblock %}

目前模板的內(nèi)容區(qū)有兩塊。第一塊是類為page-header的div輸出一個(gè)問候語。這里使用了模板條件判斷語句。在Jinja2中格式為{% if variable %}...{% else %}...{% endif %}。如果判斷條件為True則渲染if和else之間的內(nèi)容。如果判斷條件為False則渲染else和endif之間的內(nèi)容。示例模板會(huì)渲染字符串“Hello, Stranger!”當(dāng)name模板參數(shù)未定義的時(shí)候。第二塊內(nèi)容使用wtf.quick_form()函數(shù)渲染NameForm對象。

4、啟動(dòng)腳本
頂層目錄中的manage.py文件用于啟動(dòng)應(yīng)用。這個(gè)腳本會(huì)在示例7-8中展示。

示例 manage.py:啟動(dòng)腳本

#!/usr/bin/env python
import os
from app import create_app, db
from app.models import User, Role
from flask.ext.script import Manager, Shell
from flask.ext.migrate import Migrate, MigrateCommand

app = create_app(os.getenv('FLASK_CONFIG') or 'default') 
manager = Manager(app)
migrate = Migrate(app, db)

def make_shell_context():
 return dict(app=app, db=db, User=User, Role=Role)

manager.add_command("shell", Shell(make_context=make_shell_context))
manager.add_command('db', MigrateCommand)

if __name__ == '__main__': 
 manager.run()

這個(gè)腳本開始于創(chuàng)建應(yīng)用程序。使用環(huán)境變量FLASK_CONFIG,若它已經(jīng)定義了則從中獲取配置;如果沒有,則是用默認(rèn)配置。然后用于Python shell的Flask-Script、Flask-Migrate以及自定義上下文會(huì)被初始化。

為了方便,會(huì)增加一行執(zhí)行環(huán)境,這樣在基于Unix的操作系統(tǒng)上可以通過./manage.py來執(zhí)行腳本來替代冗長的python manage.py。

5、需求文件
應(yīng)用程序必須包含requirements.txt文件來記錄所有依賴包,包括精確的版本號(hào)。這很重要,因?yàn)榭梢栽诓煌臋C(jī)器上重新生成虛擬環(huán)境,例如在生產(chǎn)環(huán)境的機(jī)器上部署應(yīng)用程序。這個(gè)文件可以通過下面的pip命令自動(dòng)生成:

(venv) $ pip freeze >requirements.txt

當(dāng)安裝或更新一個(gè)包之后最好再更新一下這個(gè)文件。以下展示了一個(gè)需求文件示例:

Flask==0.10.1
Flask-Bootstrap==3.0.3.1
Flask-Mail==0.9.0
Flask-Migrate==1.1.0
Flask-Moment==0.2.0
Flask-SQLAlchemy==1.0
Flask-Script==0.6.6
Flask-WTF==0.9.4
Jinja2==2.7.1
Mako==0.9.1
MarkupSafe==0.18
SQLAlchemy==0.8.4
WTForms==1.0.5
Werkzeug==0.9.4
alembic==0.6.2
blinker==1.3
itsdangerous==0.23

當(dāng)你需要完美復(fù)制一個(gè)虛擬環(huán)境的時(shí)候,你可以運(yùn)行以下命令創(chuàng)建一個(gè)新的虛擬環(huán)境:

(venv) $ pip install -r requirements.txt

當(dāng)你讀到這時(shí),示例requirements.txt文件中的版本號(hào)可能已經(jīng)過時(shí)了。如果喜歡你可以嘗試用最近發(fā)布的包。如果遇到任何問題,你可以隨時(shí)回退到需求文件中與應(yīng)用兼容的指定版本。

6、單元測試
這個(gè)應(yīng)用非常小以至于不需要太多的測試,但是作為示例會(huì)在示例7-9中展示兩個(gè)簡單的測試定義。

示例 tests/test_basics.py:單元測試

import unittest
from flask import current_app 
from app import create_app, db

class BasicsTestCase(unittest.TestCase): 
 def setUp(self):
  self.app = create_app('testing')
  self.app_context = self.app.app_context()
  self.app_context.push()
  db.create_all()

 def tearDown(self): 
  db.session.remove() 
  db.drop_all() 
  self.app_context.pop()

 def test_app_exists(self): 
  self.assertFalse(current_app is None)

 def test_app_is_testing(self): 
  self.assertTrue(current_app.config['TESTING'])

編寫好的測試使用的是來自于Python標(biāo)準(zhǔn)庫中標(biāo)準(zhǔn)的unittest包。setUp()和tearDown()方法在每個(gè)測試之前和之后運(yùn)行,且任何一個(gè)方法必須以test_開頭作為測試來執(zhí)行。

建議:如果你想要學(xué)習(xí)更多使用Python的unittest包來寫單元測試的內(nèi)容,請參閱官方文檔。
setUp()方法嘗試創(chuàng)建一個(gè)測試環(huán)境,類似于運(yùn)行應(yīng)用程序。首先它創(chuàng)建應(yīng)用程序配置用于測試并激活上下文。這一步確保測試可以和常規(guī)請求一樣訪問current_app。然后,當(dāng)需要的時(shí)候,可以創(chuàng)建一個(gè)供測試使用的全新數(shù)據(jù)庫。數(shù)據(jù)庫和應(yīng)用程序上下文會(huì)在tearDown()方法中被移除。

第一個(gè)測試確保應(yīng)用程序?qū)嵗嬖?。第二個(gè)測試確保應(yīng)用程序在測試配置下運(yùn)行。為了確保tests目錄有效,需要在tests目錄下增加__init__.py文件,不過該文件可以為空,這樣unittest包可以掃描所有模塊并定位測試。

建議:如果你有克隆在GitHub上的應(yīng)用程序,你現(xiàn)在可以運(yùn)行g(shù)it checkout 7a來切換到這個(gè)版本的應(yīng)用程序。為了確保你已經(jīng)安裝了所有依賴集,需要運(yùn)行pip install -r requirements.txt。
為了運(yùn)行單元測試,可以在manage.py腳本中增加一個(gè)自定義的命令。

下面的例子展示如何添加測試命令。

示例 manage.pyt:單元測試啟動(dòng)腳本

@manager.command
def test():
 """Run the unit tests."""
 import unittest
 tests = unittest.TestLoader().discover('tests') 
 unittest.TextTestRunner(verbosity=2).run(tests)

manager.command裝飾器使得它可以很容易的實(shí)現(xiàn)自定義命令。被裝飾的函數(shù)名可以被當(dāng)做命令名使用,且函數(shù)的文檔字符串會(huì)顯示幫助信息。test()函數(shù)的執(zhí)行會(huì)調(diào)用unittest包中的測試運(yùn)行器。

單元測試可以像下面這樣執(zhí)行:

(venv) $ python manage.py test
test_app_exists (test_basics.BasicsTestCase) ... ok
test_app_is_testing (test_basics.BasicsTestCase) ... ok

.----------------------------------------------------------------------
Ran 2 tests in 0.001s

OK

7、數(shù)據(jù)庫啟動(dòng)
與單腳本的應(yīng)用相比,重構(gòu)后的應(yīng)用使用不同數(shù)據(jù)庫。

從環(huán)境變量中獲取的數(shù)據(jù)庫URL作為首選,默認(rèn)SQLite數(shù)據(jù)庫作為可選。三個(gè)配置中的環(huán)境變量和SQLite數(shù)據(jù)庫文件名是不一樣的。例如,開發(fā)配置的URL是從DEV_DATABASE_URL環(huán)境變量中獲取,如果沒有定義則會(huì)使用名為data-dev.sqlite的SQLite數(shù)據(jù)庫。

無論數(shù)據(jù)庫URL源的是哪一個(gè),都必須為新的數(shù)據(jù)庫創(chuàng)建數(shù)據(jù)庫表。如果使用了Flask-Migrate來保持遷移跟蹤,數(shù)據(jù)庫表可以被創(chuàng)建或更新到最近的版本通過下面的命令:

(venv) $ python manage.py db upgrade

相信與否,已經(jīng)到了第一部分結(jié)束的地方。你現(xiàn)在已經(jīng)學(xué)到了Flask必要的基本要素,但是你不確定如何將這些零散的知識(shí)組合在一起形成一個(gè)真正的應(yīng)用程序。第二部分的目的是通過開發(fā)一個(gè)完整的應(yīng)用程序來帶領(lǐng)你繼續(xù)前行。

相關(guān)文章

  • python根據(jù)出生日期返回年齡的方法

    python根據(jù)出生日期返回年齡的方法

    這篇文章主要介紹了python根據(jù)出生日期返回年齡的方法,實(shí)例分析了Python時(shí)間操作的技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-03-03
  • python操作cfg配置文件方式

    python操作cfg配置文件方式

    今天小編就為大家分享一篇python操作cfg配置文件方式,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-12-12
  • python sys模塊使用方法介紹

    python sys模塊使用方法介紹

    sys模塊是最常用的和python解釋器交互的模塊,sys模塊可供訪問由解釋器(interpreter)使用或維護(hù)的變量和與解釋器進(jìn)行交互的函數(shù),需要的朋友可以參考下
    2022-08-08
  • Python如何操作docker redis過程解析

    Python如何操作docker redis過程解析

    這篇文章主要介紹了Python如何操作docker redis過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-08-08
  • Python辦公自動(dòng)化之?dāng)?shù)據(jù)可視化與報(bào)表生成

    Python辦公自動(dòng)化之?dāng)?shù)據(jù)可視化與報(bào)表生成

    在現(xiàn)代辦公環(huán)境中,數(shù)據(jù)處理和報(bào)表生成是一項(xiàng)重要的任務(wù),本文將高效介紹如何使用Python進(jìn)行數(shù)據(jù)可視化和報(bào)表生成,讓您的辦公工作更加順利
    2023-07-07
  • 如何在代碼中安裝?Python?模塊

    如何在代碼中安裝?Python?模塊

    這篇文章主要介紹了如何在代碼中安裝Python模塊,本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-06-06
  • Python讀取Excel繪制直方圖的方法

    Python讀取Excel繪制直方圖的方法

    這篇文章主要介紹了Python讀取Excel繪制直方圖,以下將詳細(xì)介紹如何使用 Python 的?pyecharts、matplotlib?和?seaborn?三個(gè)庫從 Excel 中讀取數(shù)據(jù)并繪制直方圖(Histogram),需要的朋友可以參考下
    2025-04-04
  • pandas讀取csv格式數(shù)據(jù)時(shí)header參數(shù)設(shè)置方法

    pandas讀取csv格式數(shù)據(jù)時(shí)header參數(shù)設(shè)置方法

    本文主要介紹了pandas讀取csv格式數(shù)據(jù)時(shí)header參數(shù)設(shè)置方法,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-02-02
  • 基于python log取對數(shù)詳解

    基于python log取對數(shù)詳解

    今天小編就為大家分享一篇基于python log取對數(shù)詳解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-06-06
  • Python圖像運(yùn)算之腐蝕與膨脹詳解

    Python圖像運(yùn)算之腐蝕與膨脹詳解

    這篇文章將詳細(xì)講解開始圖像形態(tài)學(xué)知識(shí),主要介紹圖像腐蝕處理和膨脹處理。文中的示例代碼簡潔易懂,感興趣的小伙伴快跟隨小編一起學(xué)習(xí)一下吧
    2022-05-05

最新評論