如何使用 Flask 和 Python 3 創建您的首个網絡應用

作者選擇了自由與開源基金作為Write for DOnations計劃的一部分接受捐贈。

引言

Flask是一個輕量級的Python網頁框架,為使用Python語言創建網頁應用程式提供了有用的工具和功能。它給予開發者靈活性,並且對新手開發者來說是一個易於上手的框架,因為你可以僅用一個Python文件快速構建一個網頁應用程式。Flask也是可擴展的,不會強制要求特定的目錄結構,也不需要在開始前編寫複雜的樣板代碼。

學習Flask將使你能夠快速創建Python網頁應用程式。你可以利用Python庫為你的網頁應用程式添加高級功能,比如將數據存儲在數據庫中,或驗證網頁表單。

在本教程中,您將構建一個小型網絡應用程式,在瀏覽器上渲染 HTML 文本。您將安裝 Flask,編寫並運行一個 Flask 應用程式,並以開發模式運行該應用程式。您將使用路由來顯示各種網頁,這些網頁在您的網絡應用程式中具有不同的用途。您還將使用視圖函數,允許用戶通過動態路由與應用程式進行交互。最後,您將使用調試器來排查錯誤。

前提條件

步驟1 — 安裝Flask

在這一步中,您將啟動您的Python環境並使用pip套件安裝程式來安裝Flask。

首先,如果您尚未啟動,請激活您的編程環境:

  1. source env/bin/activate

一旦您激活了編程環境,使用pip install命令安裝Flask:

  1. pip install flask

安裝完成後,您將在最後部分的輸出中看到已安裝的套件列表,類似於以下內容:

Output
... Installing collected packages: Werkzeug, MarkupSafe, Jinja2, itsdangerous, click, flask Successfully installed Jinja2-3.0.1 MarkupSafe-2.0.1 Werkzeug-2.0.1 click-8.0.1 flask-2.0.1 itsdangerous-2.0.1

這意味著安裝Flask的同時也安裝了幾個其他套件。這些套件是Flask執行不同功能所需的依賴項。

您已經創建了項目資料夾、虛擬環境並安裝了Flask。現在可以繼續設置一個簡單的應用程式。

步驟2 — 創建一個簡單的應用程式

現在您已經設置好編程環境,將開始使用 Flask。在這一步中,您將在一個 Python 文件內創建一個小型 Flask 網絡應用程序,在其中編寫 HTML 代碼以在瀏覽器中顯示。

在您的 flask_app 目錄中,打開一個名為 app.py 的文件進行編輯,使用 nano 或您喜愛的文本編輯器:

  1. nano app.py

app.py 文件中寫入以下代碼:

flask_app/app.py

from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello():
    return '<h1>Hello, World!</h1>'

保存並關閉文件。

在上述代碼塊中,您首先從 flask 包中導入 Flask 對象。然後使用它來創建您的 Flask 應用程序實例,並將其命名為 app。您傳遞了特殊的變量 __name__,該變量保存當前 Python 模塊的名稱。這個名稱告訴實例它的位置;Flask 需要這個信息來在幕後設置一些路徑。

一旦創建了 app 實例,您就可以使用它來處理傳入的網絡請求並向用戶發送響應。@app.route 是一個裝飾器,它將一個普通的 Python 函數轉換為 Flask 的視圖函數,該函數將其返回值轉換為 HTTP 響應,由 HTTP 客戶端(如網絡瀏覽器)顯示。您將值 '/' 傳遞給 @app.route(),表示該函數將響應主 URL / 的網絡請求。

hello() 視圖函數返回字符串 '<h1>Hello, World!</h1>' 作為 HTTP 響應。

你現在有一個簡單的 Flask 應用程序在名為 app.py 的 Python 文件中,下一步,你將運行該應用程序以在網頁瀏覽器中查看 hello() 視圖函數的渲染結果。

步驟 3 — 運行應用程序

在創建包含 Flask 應用程序的文件後,你將使用 Flask 命令行界面啟動開發服務器,並在瀏覽器中渲染你在上一步中作為 hello() 視圖函數返回值編寫的 HTML 代碼。

首先,在激活虛擬環境的情況下進入 flask_app 目錄,使用以下命令告訴 Flask 應用程序的位置(在你的情況下是 app.py)(在 Windows 上,使用 set 而不是 export):

  1. export FLASK_APP=app

然後指定你希望在開發模式下運行應用程序(這樣你可以使用調試器捕捉錯誤),使用 FLASK_ENV 環境變量:

  1. export FLASK_ENV=development

最後,使用 flask run 命令運行應用程序:

  1. flask run

一旦應用程序運行,輸出將類似如下:

Output
* Serving Flask app "app" (lazy loading) * Environment: development * Debug mode: on * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) * Restarting with stat * Debugger is active! * Debugger PIN: 296-353-699

前面的輸出包含多條信息,例如:

  • 您正在運行的應用程式名稱("app")。
  • 應用程式正在運行的環境(development)。
  • Debug mode: on表示 Flask 調試器正在運行。這在開發過程中非常有用,因為它在出錯時提供詳細的錯誤信息,使故障排除更加容易。
  • 該應用程式正在本地 URL http://127.0.0.1:5000/ 上運行。127.0.0.1 是代表您機器上 localhost 的 IP,而 :5000 是端口号。

打開瀏覽器並輸入 URL http://127.0.0.1:5000/。您將看到作為回應的 <h1> 標題中的文字 Hello, World!。這證實了您的應用程式已成功運行。

如果您想停止開發服務器,請按 CTRL+C

警告:Flask 在開發環境中使用一個簡單的網頁伺服器來運行您的應用程式,這也意味著 Flask 調試器正在運行,以便更容易捕捉錯誤。您不應該在生產部署中使用這個開發伺服器。更多資訊請參閱 Flask 文件中的部署選項頁面。您也可以查看這個使用 Gunicorn 部署 Flask 的教程使用 uWSGI 的教程,或者您可以按照如何在 App Platform 上使用 Gunicorn 部署 Flask 應用程式教程,使用 DigitalOcean App Platform 部署您的 Flask 應用程式。

要繼續開發 app.py 應用程式,請保持開發伺服器運行並打開另一個終端窗口。進入 flask_app 目錄,啟動虛擬環境,設置環境變數 FLASK_ENVFLASK_APP,並繼續進行下一步。(這些命令在本步驟前面已列出。)

注意:當打開一個新的終端,或者當你關閉正在運行開發服務器的終端並希望重新運行它時,重要的是要記住激活虛擬環境並設置環境變量 FLASK_ENVFLASK_APP,以便 flask run 命令能夠正常工作。

你只需要在一個終端窗口中運行一次服務器。

當 Flask 應用程序的開發服務器已經在運行時,無法使用相同的 flask run 命令運行另一個 Flask 應用程序。這是因為 flask run 默認使用端口号 5000,一旦被占用,它就無法用於運行另一個應用程序,因此你會收到類似以下的錯誤:

Output
OSError: [Errno 98] Address already in use

要解決這個問題,可以通過 CTRL+C 停止當前正在運行的服務器,然後再次運行 flask run,或者如果你想同時運行兩個應用程序,你可以為 -p 參數傳遞一個不同的端口号,例如,要在端口 5001 上運行另一個應用程序,請使用以下命令:

  1. flask run -p 5001

這樣你就可以在一個應用程序運行在 http://127.0.0.1:5000/ 上,另一個運行在 http://127.0.0.1:5001/ 上,如果你願意的話。

現在你已經擁有了一個小型的 Flask 網絡應用程序。你已經運行了你的應用程序並在網絡瀏覽器上顯示了信息。接下來,你將學習有關路由的知識,以及如何使用它們來服務多個網頁。

步驟 4 — 路由和視圖函數

在這一步中,您將為應用程序添加幾個路由,以根據請求的 URL 顯示不同的頁面。您還將學習視圖函數以及如何使用它們。

一個 路由 是用戶在瀏覽器中訪問您的 Web 應用程序時可以使用的 URL,以確定用戶獲得的內容。例如,http://127.0.0.1:5000/ 可能是用於顯示索引頁面的主路由。URL http://127.0.0.1:5000/about 可能是另一個用於關於頁面的路由,該頁面向訪問者提供有關您的 Web 應用程序的一些信息。同樣,您可以創建一個允許用戶在 http://127.0.0.1:5000/login 登錄您的應用程序的路由。

您的 Flask 應用程序目前有一個路由,用於服務請求主 URL (http://127.0.0.1:5000/) 的用戶。為了演示如何向應用程序添加新的網頁,您將編輯應用程序文件,以在 http://127.0.0.1:5000/about 添加另一個路由,提供有關您的 Web 應用程序的信息。

首先,打開您的 app.py 文件進行編輯:

  1. nano app.py

通過在文件末尾添加以下突出顯示的代碼來編輯文件:

flask_app/app.py
from flask import Flask

app = Flask(__name__)


@app.route('/')
def hello():
    return '<h1>Hello, World!</h1>'


@app.route('/about/')
def about():
    return '<h3>This is a Flask web application.</h3>'

保存並關閉文件。

你新增了一個名為 about() 的函數。此函數經過 @app.route() 裝飾器裝飾,使其變成一個視圖函數,負責處理對 http://127.0.0.1:5000/about 端點的請求。

在開發伺服器運行時,使用瀏覽器訪問以下網址:

http://127.0.0.1:5000/about

你將看到文字 This is a Flask web application.<h3> HTML 標題的形式呈現。

你也可以為一個視圖函數設定多個路由。例如,你可以在 //index/ 兩個路徑下提供首頁。為此,打開你的 app.py 文件進行編輯:

  1. nano app.py

通過為 hello() 視圖函數添加另一個裝飾器來編輯文件:

flask_app/app.py
from flask import Flask

app = Flask(__name__)

@app.route('/')
@app.route('/index/')
def hello():
    return '<h1>Hello, World!</h1>'

@app.route('/about/')
def about():
    return '<h3>This is a Flask web application.</h3>'

保存並關閉文件。

添加此新裝飾器後,你可以在 http://127.0.0.1:5000/http://127.0.0.1:5000/index 兩個路徑下訪問首頁。

你現在了解了路由是什麼,如何使用它們來創建視圖函數,以及如何為你的應用程序添加新路由。接下來,你將使用動態路由來允許用戶控制應用程序的響應。

步驟 5 — 動態路由

在這一步中,您將使用動態路由來允許用戶與應用程序進行互動。您將創建一個路由,將通過 URL 傳遞的單詞大寫,並創建一個路由,將兩個數字相加並顯示結果。

通常,用戶不會通過手動編輯 URL 來與網絡應用程序互動。相反,用戶與頁面上的元素互動,這些元素會根據用戶的輸入和操作導向不同的 URL,但為了本教程的目的,您將編輯 URL 以演示應用程序如何根據不同的 URL 做出不同的響應。

首先,打開您的 app.py 文件進行編輯:

  1. nano app.py

如果您允許用戶向您的網絡應用程序提交某些內容,例如您將在接下來的編輯中在 URL 中提交的值,您應該始終記住,您的應用程序不應直接顯示不受信任的數據(用戶提交的數據)。為了安全地顯示用戶數據,請使用 markupsafe 包附帶的 escape() 函數,該包在安裝 Flask 時已經安裝。

編輯 app.py 並在 Flask 導入上方添加以下行:

flask_app/app.py
from markupsafe import escape
from flask import Flask

# ...

然後,在文件末尾添加以下路由:

flask_app/app.py
# ...

@app.route('/capitalize/<word>/')
def capitalize(word):
    return '<h1>{}</h1>'.format(escape(word.capitalize()))

保存並關閉文件。

這條新路由包含一個可變部分 `<word>`。這告訴 Flask 從 URL 中提取值並將其傳遞給視圖函數。URL 變量 `<word>` 將一個關鍵字參數傳遞給 `capitalize()` 視圖函數。該參數的名稱與 URL 變量相同(在本例中為 `word`)。通過這樣做,您可以訪問通過 URL 傳遞的單詞,並使用 Python 中的 `capitalize()` 方法響應其大寫版本。

您使用之前導入的 `escape()` 函數將 `word` 字符串渲染為文本。這對於避免跨站腳本(XSS)攻擊至關重要。如果用戶提交的是惡意 JavaScript 而非單詞,`escape()` 將其渲染為文本,瀏覽器不會執行它,從而保護您的 Web 應用程序安全。

要在 `<h1>` HTML 標題內顯示大寫的單詞,您使用 Python 的 `format()` 方法,更多關於此方法的內容,請參閱如何在 Python 3 中使用字符串格式化工具

在開發服務器運行時,打開瀏覽器並訪問以下 URL。您可以將突出顯示的單詞替換為您選擇的任何單詞。

http://127.0.0.1:5000/capitalize/hello
http://127.0.0.1:5000/capitalize/flask
http://127.0.0.1:5000/capitalize/python

您可以在頁面上看到 URL 中的單詞在大寫的 `<h1>` 標籤中。

您也可以在路由中使用多個變數。為了展示這一點,您將新增一個路由,該路由將兩個正整數相加並顯示結果。

打開您的 app.py 檔案進行編輯:

  1. nano app.py

在檔案末尾新增以下路由:

flask_app/app.py
# ...

@app.route('/add/<int:n1>/<int:n2>/')
def add(n1, n2):
    return '<h1>{}</h1>'.format(n1 + n2)

保存並關閉檔案。

在這個路由中,您使用了 特殊轉換器 int 與 URL 變數(/add/<int:n1>/<int:n2>/),該轉換器僅接受正整數。默認情況下,URL 變數被假定為字串並作為字串處理。

在開發伺服器運行時,打開瀏覽器並訪問以下 URL:

http://127.0.0.1:5000/add/5/5/

結果將是這兩個數字的和(在這種情況下為 10)。

您現在已經了解了如何使用動態路由根據請求的 URL 在單一路由中顯示不同的回應。接下來,您將學習如何在出現錯誤時對 Flask 應用程式進行故障排除和調試。

步驟 6 — 調試 Flask 應用程式

在開發網頁應用程式時,您經常會遇到應用程式顯示錯誤而非您預期的行為。您可能拼錯變數或忘記定義或匯入函數。為了使解決這些問題更容易,Flask 在開發模式下運行應用程式時提供了調試器。在這一步,您將學習如何使用 Flask 調試器來修復應用程式中的錯誤。

為了展示如何處理錯誤,您將創建一個從用戶名列表中向用戶打招呼的路由。

打開您的 app.py 文件進行編輯:

  1. nano app.py

在文件末尾添加以下路由:

flask_app/app.py
# ...

@app.route('/users/<int:user_id>/')
def greet_user(user_id):
    users = ['Bob', 'Jane', 'Adam']
    return '<h2>Hi {}</h2>'.format(users[user_id])

保存並關閉文件。

在上面的路由中,greet_user() 視圖函數從 user_id URL 變數接收一個 user_id 參數。您使用 int 轉換器來接受正整數。在函數內部,您有一個名為 users 的 Python 列表,其中包含三個代表用戶名的字串。視圖函數根據提供的 user_id 返回一個字串。如果 user_id0,則響應將是 Hi Bob 在一個 <h2> 標籤中,因為 Bob 是列表中的第一個項目(users[0] 的值)。

在開發伺服器運行時,打開您的瀏覽器並訪問以下 URL:

http://127.0.0.1:5000/users/0
http://127.0.0.1:5000/users/1
http://127.0.0.1:5000/users/2

您將收到以下響應:

Output
Hi Bob Hi Jane Hi Adam

到目前為止,這種方法效果良好,但當你為一個不存在的用戶請求問候時,它可能會出錯。為了展示 Flask 調試器的工作原理,請訪問以下 URL:

http://127.0.0.1:5000/users/3

你會看到一個類似這樣的頁面:

在頁面頂部,它會顯示 Python 異常的名稱,即 IndexError,表明列表索引(在本例中為 3)超出了列表的範圍(該範圍僅從 02,因為列表只有三個項目)。在調試器中,你可以看到回溯信息,它告訴你引發此異常的代碼行。

回溯的最後兩行通常會指出錯誤的源頭。在你的情況下,這些行可能類似於以下內容:

File "/home/USER/flask_app/app.py", line 28, in greet_user
    return '<h2>Hi {}</h2>'.format(users[user_id])

這表明錯誤源自 app.py 文件中的 greet_user() 函數,具體是在 return 行。

了解引發異常的原始行將有助於你確定代碼中哪裡出錯,並決定如何修復它。

在這種情況下,你可以使用一個簡單的 try...except 子句來修復此錯誤。如果請求的 URL 索引超出列表範圍,用戶將收到一個 404 Not Found 錯誤,這是一個 HTTP 錯誤,告訴用戶他們正在尋找的頁面不存在。

打開你的 app.py 文件進行編輯:

  1. nano app.py

要回應 HTTP 404 錯誤,你需要 Flask 的 abort() 函數,它可用於生成 HTTP 錯誤回應。修改檔案中的第二行以同時匯入此函數:

flask_app/app.py
from markupsafe import escape
from flask import Flask, abort

然後編輯 greet_user() 視圖函數,使其如下所示:

flask_app/app.py
# ...

@app.route('/users/<int:user_id>/')
def greet_user(user_id):
    users = ['Bob', 'Jane', 'Adam']
    try:
        return '<h2>Hi {}</h2>'.format(users[user_id])
    except IndexError:
        abort(404)

你使用 try 來測試 return 表達式是否有錯誤。如果沒有錯誤,即 user_id 的值與 users 列表中的某個索引相匹配,應用程式將以適當的問候回應。如果 user_id 的值超出列表範圍,將引發 IndexError 異常,你使用 except 捕獲該錯誤,並使用 abort() Flask 輔助函數回應 HTTP 404 錯誤。

現在,在開發伺服器運行時,再次訪問該 URL:

http://127.0.0.1:5000/users/3

這次你會看到一個標準的 404 錯誤頁面,告知使用者該頁面不存在。

到本教程結束時,你的 app.py 檔案將如下所示:

flask_app/app.py
from markupsafe import escape
from flask import Flask, abort

app = Flask(__name__)


@app.route('/')
@app.route('/index/')
def hello():
    return '<h1>Hello, World!</h1>'


@app.route('/about/')
def about():
    return '<h3>This is a Flask web application.</h3>'

@app.route('/capitalize/<word>/')
def capitalize(word):
    return '<h1>{}</h1>'.format(escape(word.capitalize()))

@app.route('/add/<int:n1>/<int:n2>/')
def add(n1, n2):
    return '<h1>{}</h1>'.format(n1 + n2)

@app.route('/users/<int:user_id>/')
def greet_user(user_id):
    users = ['Bob', 'Jane', 'Adam']
    try:
        return '<h2>Hi {}</h2>'.format(users[user_id])
    except IndexError:
        abort(404)

你現在對如何使用 Flask 調試器來排查錯誤並幫助你確定解決這些錯誤的適當行動有了大致了解。

結論

你現在已經大致了解 Flask 是什麼,如何安裝它,以及如何利用它來編寫一個 Web 應用程式,如何運行開發伺服器,以及如何使用路由和視圖函數來展示不同用途的網頁。你也學會了如何使用動態路由來讓使用者透過 URL 與你的 Web 應用程式互動,以及如何使用調試器來排解錯誤。

如果你想進一步了解 Flask,可以查看Flask 主題頁面

Source:
https://www.digitalocean.com/community/tutorials/how-to-create-your-first-web-application-using-flask-and-python-3