作者選擇了自由與開源基金作為Write for DOnations計劃的一部分接受捐贈。
引言
網頁表單,例如文字欄位和文字區域,允許使用者向您的應用程式發送數據,以便執行某個動作,或向應用程式發送更大的文字區域。例如,在社交媒體應用程式中,您可能會提供一個方塊,讓使用者可以添加新內容到他們的頁面。另一個例子是登錄頁面,您會提供一個文字欄位供使用者輸入用戶名,以及一個密碼欄位供他們輸入密碼。伺服器(在此情況下是您的Flask應用程式)會使用使用者提交的數據,如果數據有效,則會登錄他們;如果數據不正確,則會回應類似無效憑證!
的訊息,告知使用者他們提交的數據不正確。
Flask 是一個輕量級的 Python 網頁框架,為使用 Python 語言創建網頁應用程式提供了有用的工具和功能。在本教程中,您將構建一個小型網頁應用程式,展示如何使用網頁表單。該應用程式將有一個頁面用於顯示存儲在 Python 列表中的消息,以及一個頁面用於添加新消息。您還將使用 消息閃現 來告知用戶在提交無效數據時的錯誤。
先決條件
-
本地 Python 3 編程環境,請按照 如何安裝和設置本地編程環境 for Python 3 系列中適用於您發行版的教程進行操作。在本教程中,我們將稱項目目錄為
flask_app
。 -
對基本Flask概念的理解,例如路由、視圖函數和模板。如果您不熟悉Flask,請查看如何使用Flask和Python創建您的首個Web應用程序和如何在Flask應用程序中使用模板。
-
對基本HTML概念的理解。您可以回顧我們的如何使用HTML構建網站教程系列以獲取背景知識。
第一步 — 顯示訊息
在這一步中,您將創建一個Flask應用程式,其主頁用於顯示存儲在Python字典列表中的訊息。
首先,打開一個名為app.py
的新文件進行編輯:
在app.py
文件中添加以下程式碼,以創建一個帶有單一路由的Flask伺服器:
保存並關閉文件。
在這個文件中,您首先從flask
套件導入了Flask
類和render_template()
函數。然後使用Flask
類創建了一個新的應用程式實例,稱為app
,並傳遞了特殊的__name__
變量,這是Flask在幕後設置一些路徑所必需的。模板渲染在教程如何在Flask應用程式中使用模板中有所介紹。
接著創建了一個名為messages
的全局Python列表,其中包含Python字典。每個字典有兩個鍵:title
用於訊息標題,content
用於訊息內容。這是一個簡化的數據存儲方法示例;在實際應用中,您會使用一個能永久保存數據並允許更高效操作的數據庫。
在建立 Python 列表後,您使用 @app.route()
裝飾器來創建一個名為 index()
的視圖函數。在其中,您返回對 render_template()
函數的調用,這指示 Flask 該路由應顯示一個 HTML 模板。您將此模板命名為 index.html
(稍後將創建它),並向其傳遞一個名為 messages
的變量。該變量保存了您先前聲明的 messages
列表作為值,並使其可被 HTML 模板訪問。視圖函數在教程《如何使用 Flask 和 Python 3 創建您的首個 Web 應用》中有詳細介紹。
接下來,在您的 flask_app
目錄中創建一個 templates
文件夾,Flask 會在其中搜索模板,然後打開一個名為 base.html
的模板文件,該文件將包含其他模板繼承以避免代碼重複的代碼:
在 base.html
文件中添加以下代碼,以創建帶有導航欄和內容塊的基本模板:
保存並關閉文件。
這個基礎模板包含了所有你會在其他模板中重複使用的HTML樣板。title
區塊將被替換以設定每個頁面的標題,而content
區塊將被替換為每個頁面的內容。導覽列有兩個連結,一個是索引頁,你使用url_for()
輔助函數來連結到index()
視圖函數,另一個是關於頁面,如果你選擇在應用程式中包含一個。
接下來,打開一個名為index.html
的模板。這是你參考在app.py
文件中的模板:
將以下代碼添加到其中:
保存並關閉文件。
在這段代碼中,你擴展了base.html
模板並替換了content
區塊的內容。你使用了一個<h1>
標題,同時也作為標題。
你在{% for message in messages %}
這一行中使用了Jinja for
循環來遍歷messages
列表中的每個消息。你使用了一個<div>
標籤來包含消息的標題和內容。你將標題顯示在<h3>
標題中,而內容則顯示在<p>
標籤中。
當你在激活了虛擬環境的flask_app
目錄中時,使用FLASK_APP
環境變數告訴Flask關於應用程式(在此例中是app.py
)的信息:
接著,將 FLASK_ENV
環境變數設定為 development
,以開發模式運行應用程式並啟用調試器。更多關於 Flask 調試器的資訊,請參閱 如何在 Flask 應用程式中處理錯誤。使用以下命令進行設定(在 Windows 上,使用 set
而非 export
):
接下來,運行應用程式:
開發伺服器運行後,使用瀏覽器訪問以下 URL:
http://127.0.0.1:5000/
你將在首頁上看到 messages
列表中的訊息:
現在你已經設置了網頁應用程式並顯示了訊息,接下來需要一種方法讓用戶能在首頁添加新訊息。這可以透過網頁表單來實現,你將在下一步中設置。
步驟 2 — 設置表單
在這一步中,你將創建一個頁面,允許用戶透過網頁表單向訊息列表添加新訊息。
保持開發伺服器運行,並打開一個新的終端窗口。
首先,打開你的 app.py
文件:
在文件末尾添加以下路由:
保存並關閉文件。
這個 /create
路由具有 methods
參數,其值為元組 ('GET', 'POST')
,用於接受 GET
和 POST
請求。GET
和 POST
是 HTTP 方法。默認情況下,只接受 GET
請求,這些請求用於檢索數據,例如向服務器請求索引頁或關於頁。POST
請求則用於向特定路由提交數據,這通常會改變服務器上的數據。
在此示例中,您將使用 GET
請求來請求 create
頁面。Create 頁面將包含一個帶有輸入字段和提交按鈕的網頁表單。當用戶填寫網頁表單並點擊提交按鈕時,會向 /create
路由發送一個 POST
請求。在那裡處理請求,驗證提交的數據以確保用戶未提交空表單,並將其添加到 messages
列表中。
目前,create()
視圖函數僅做一件事:當接收到常規的 GET 請求時,渲染一個名為 create.html
的模板。您現在將創建此模板,然後在下一步中編輯該函數以處理 POST
請求。
打開一個新的模板文件,名為 create.html
:
向其中添加以下代碼:
保存並關閉文件。
在這段程式碼中,您擴展了 `base.html
` 模板,並將 `content
` 區塊替換為一個 `<h1>
` 標題,作為頁面的標題。在 `<form>
` 標籤中,您將 `method
` 屬性設置為 `post
`,以便表單數據以 `POST
` 請求的形式發送到伺服器。
在表單中,您有一個名為 `title
` 的文字輸入欄位;這是您將在應用程式中用於訪問標題表單數據的名稱。您為 `<input>
` 標籤設置了一個 `value
` 為 `{{ request.form['title'] }}
`。這在恢復用戶輸入的數據時非常有用,以免在出現問題時丟失數據。例如,如果用戶忘記填寫必需的 `content
` 文字區域,請求將發送到伺服器,並且錯誤消息將作為響應返回,但標題中的數據不會丟失,因為它將保存在 `request
` 全局對象中,並且可以通過 `request.form['title']
` 訪問。
在標題輸入欄位之後,您添加了一個名為 `content
` 的文字區域,其值為 `{{ request.form['content'] }}
`,原因與前面提到的相同。
最後,您在表單末尾添加了一個提交按鈕。
現在,在開發伺服器運行時,使用您的瀏覽器導航到 `/create
` 路由:
http://127.0.0.1:5000/create
您將看到一個“添加新消息”頁面,其中包含一個消息標題的輸入欄位、一個消息內容的文字區域和一個提交按鈕。
此表單向您的 create()
視圖函數提交一個 POST
請求。然而,該函數中尚未有處理 POST
請求的代碼,因此在填寫表單並提交後不會發生任何事情。在下一步中,您將處理表單提交時的傳入 POST
請求。您將檢查提交的數據是否有效(非空),並將消息標題和內容添加到 messages
列表中。
步驟 3 — 處理表單請求
在此步驟中,您將在應用端處理表單請求。您將通過前一步創建的表單訪問用戶提交的數據,並將其添加到消息列表中。您還將使用 消息閃現 來通知用戶在提交無效數據時的情況。閃現消息 僅顯示一次,並且在下一個請求時消失(例如,如果您導航到另一個頁面)。
打開 app.py
文件進行編輯:
首先,您將從 Flask 框架導入以下內容:
- 全局
request
對象,用於訪問將通過上一步構建的 HTML 表單提交的傳入請求數據。 url_for()
函數用於生成 URL。- 使用
flash()
函數在處理請求時顯示消息(告知用戶一切順利,或在提交的數據無效時通知他們問題所在)。 - 使用
redirect()
函數將客戶端重定向到其他位置。
將這些導入添加到文件的第一行:
flash()
函數將閃現消息存儲在客戶端瀏覽器會話中,這需要設置一個 密鑰。此密鑰用於保護會話,使 Flask 能夠記住從一次請求到另一次請求的信息,例如從新消息頁面移動到索引頁面。用戶可以訪問存儲在會話中的信息,但除非他們擁有密鑰,否則無法修改它,因此您絕不能允許任何人訪問您的密鑰。更多信息請參閱 Flask 文檔中的會話部分。
密鑰應為一串長的隨機字符串。您可以使用 os
模組中的 os.urandom()
方法生成密鑰,該方法返回一串適合加密用途的隨機字節。要使用它獲取隨機字符串,請打開一個新的終端並使用以下命令打開 Python 交互式 shell:
在 Python 交互式 shell 中,從標準庫導入 os
模組並如下調用 os.urandom()
方法:
您將獲得類似以下字符串:
Output
'df0331cefc6c2b9a5d0208a726a5d1c0fd37324feba25506'
您可以使用獲得的字符串作為您的密鑰。
要設置密鑰,通過 app.config
對象向您的應用程序添加一個 SECRET_KEY
配置。在定義 messages
變量之前,直接在 app
定義後添加它:
接下來,修改 create()
視圖函數,使其完全如下所示:
在 if
語句中,您確保只有在請求是 POST
請求時(通過比較 request.method == 'POST'
),後續代碼才會執行。
接著,從request.form
物件中提取提交的標題和內容,該物件讓您能夠訪問請求中的表單數據。如果未提供標題,條件if not title
將被滿足。在這種情況下,您將使用flash()
函數向用戶顯示一條消息,告知他們標題是必需的。這將消息添加到閃現消息列表中。稍後,您將在base.html
模板中顯示這些消息。同樣地,如果未提供內容,條件elif not content
將被滿足。如果是這樣,您將'Content is required!'
消息添加到閃現消息列表中。
如果標題和消息內容正確提交,您將使用messages.append({'title': title, 'content': content})
行將一個新的字典添加到messages
列表中,包含用戶提供的標題和內容。然後,您使用redirect()
函數將用戶重定向到索引頁。您使用url_for()
函數來鏈接到索引頁。
保存並關閉文件。
現在,使用您的網頁瀏覽器導航到/create
路由:
http://127.0.0.1:5000/create
在表單中填寫您選擇的標題和一些內容。提交表單後,您將在索引頁上看到新消息的列表。
最後,您將在base.html
模板中顯示閃現消息,並在導航欄中添加“新消息”頁面的鏈接,以便輕鬆訪問此新頁面。打開基礎模板文件:
編輯檔案,在導航欄中的 FlaskApp 連結後面新增一個新的 `<a>
` 標籤。然後在 `<nav>
` 標籤內部,直接在內容區塊上方新增一個新的 `for
` 循環,用於顯示導航欄下方的閃現訊息。這些訊息可通過 Flask 提供的特殊函數 `get_flashed_messages()
` 獲取。接著,為每條訊息添加一個名為 `alert
` 的類別屬性,並在 `<style>
` 標籤內為其設定一些 CSS 屬性:
保存並關閉檔案,然後在瀏覽器中重新載入 `https://127.0.0.1:5000
`。導航欄現在將有一個指向 `/create
` 路由的“創建”項目。
要查看閃現訊息的工作原理,請前往“創建”頁面,點擊提交按鈕而不填寫兩個欄位。您將收到一條類似以下的訊息:
返回首頁,您會發現導航欄下方的閃現訊息消失了,儘管它們是作為基礎模板的一部分顯示的。如果不是閃現訊息,它們也會在首頁上顯示,因為首頁也繼承自基礎模板。
嘗試提交一個只有標題但沒有內容的表單。你會看到訊息“內容是必需的!”。點擊導覽列中的 FlaskApp 連結返回索引頁,然後點擊返回按鈕回到創建頁面。你會發現訊息內容仍然存在。這只有在點擊返回按鈕時才有效,因為它保存了之前的請求。點擊導覽列中的創建連結會發送一個新請求,這會清除表單,因此閃現訊息將會消失。
現在你已經知道如何接收用戶輸入,如何驗證它,以及如何將其添加到數據源中。
注意:
你添加到 messages
列表中的訊息在伺服器停止時會消失,因為 Python 列表僅保存在記憶體中,要永久保存你的訊息,你需要使用像 SQLite 這樣的數據庫。查看如何在 Python 3 中使用 sqlite3 模組以學習如何使用 SQLite 和 Python。
結論
你創建了一個 Flask 應用程式,用戶可以在索引頁上顯示的訊息列表中添加訊息。你創建了一個網頁表單,處理了用戶透過表單提交的數據,並將其添加到你的訊息列表中。你還使用了閃現訊息來通知用戶在提交無效數據時的情況。
若您想深入瞭解 Flask,請參閱Flask系列中的其他教程。
Source:
https://www.digitalocean.com/community/tutorials/how-to-use-web-forms-in-a-flask-application