Visual Studio Code 中的 Flask 教學課程

Flask 是一個輕量級的 Python Web 應用程式框架,提供了 URL 路由和頁面渲染的基礎功能。

Flask 被稱為「微」(micro) 框架,是因為它不直接提供表單驗證、資料庫抽象、身份驗證等功能。這些功能是由稱為 Flask 擴充功能的特殊 Python 套件所提供。這些擴充功能與 Flask 無縫整合,看起來就像 Flask 本身的一部分。例如,Flask 沒有提供頁面模板引擎,但安裝 Flask 時會預設包含 Jinja 模板引擎。為方便起見,我們通常將這些預設功能視為 Flask 的一部分。

在本 Flask 教學課程中,您將建立一個包含三個頁面的簡單 Flask 應用程式,這些頁面使用共同的基礎模板。在此過程中,您將體驗 Visual Studio Code 的多項功能,包括使用終端機、編輯器、偵錯工具、程式碼片段 (code snippets) 等。

本 Flask 教學課程的完整程式碼專案可在 GitHub 上找到:python-sample-vscode-flask-tutorial

如果您遇到任何問題,可以在 Python 擴充功能討論問答 (Discussions Q&A) 中搜尋解答或提問。

先決條件

若要順利完成此 Flask 教學課程,您必須執行以下步驟(這些步驟與一般 Python 教學課程中的步驟相同):

  1. 安裝 Python 擴充功能

  2. 安裝一個 Python 3 版本(本教學課程即基於此編寫)。選項包括

    • (所有作業系統) 從 python.org 下載;通常使用頁面上第一個出現的下載 (Download) 按鈕。
    • (Linux) 內建的 Python 3 安裝運作良好,但若要安裝其他 Python 套件,您必須在終端機中執行 sudo apt install python3-pip
    • (macOS) 在 macOS 上使用 Homebrew 透過 brew install python3 進行安裝。
    • (所有作業系統) 從 Anaconda 下載(用於資料科學目的)。
  3. 在 Windows 上,請確保您的 Python 解譯器路徑已包含在 PATH 環境變數中。您可以透過在命令提示字元中執行 path 來檢查該路徑。如果沒有包含 Python 解譯器的資料夾,請開啟 Windows 設定,搜尋「環境」,選擇編輯您的帳戶環境變數,然後編輯 Path 變數以包含該資料夾。

為 Flask 教學課程建立專案環境

在本節中,您將建立一個安裝了 Flask 的虛擬環境。使用虛擬環境可以避免將 Flask 安裝到全域 Python 環境中,並讓您精確控制應用程式所使用的程式庫。

Python 環境擴充功能支援多種環境類型,包括 venv、conda、poetry 等。本教學課程使用 venv,因為它是 Python 內建的且不需要額外的工具。其他環境類型的步驟類似 — 請參閱 建立環境以了解詳情。

  1. 在您的檔案系統上,為此教學課程建立一個資料夾,例如 hello_flask

  2. 在終端機中導覽至該資料夾並執行 code .,或執行 VS Code 並使用檔案 (File) > 開啟資料夾 (Open Folder) 指令,在 VS Code 中開啟此資料夾。

  3. 使用 Python: Create Environment (Python:建立環境) 指令建立虛擬環境。

    1. 開啟命令選擇區 (⇧⌘P (Windows, Linux Ctrl+Shift+P))
    2. 搜尋並選取 Python: Create Environment (Python: 建立環境)
    3. 選取 Venv 以建立 venv 環境
    4. 選取要用於環境的 Python 解譯器

    VS Code 會在您的工作區中建立一個 .venv 資料夾,並自動選取該新環境。

    提示

    您也可以使用 Python 側邊欄來建立環境。展開 Environment Managers (環境管理員) 並選取 + 按鈕進行快速建立,這會使用合適的預設設定。

    Flask tutorial: opening the Command Palette in VS Code

  4. 使用下列其中一種方法在虛擬環境中安裝 Flask:

    使用套件管理 UI

    1. Python 側邊欄中,展開 Environment Managers (環境管理員)
    2. 對您的 .venv 環境按右鍵並選取 Manage Packages (管理套件)
    3. 搜尋 flask 並選取 Install (安裝)

    使用終端機

    從命令選擇區執行 Terminal: Create New Terminal (終端機: 建立新終端機) (⌃⇧` (Windows, Linux Ctrl+Shift+`)),這會建立一個終端機並自動啟動虛擬環境。然後執行

    python -m pip install flask
    

您現在擁有一個獨立的環境,準備好編寫 Flask 程式碼了。當您開啟新的終端機時,VS Code 會自動啟用該環境。如果您在 VS Code 之外開啟個別的命令提示字元或終端機,請透過執行 source .venv/bin/activate (Linux/macOS) 或 .venv\Scripts\Activate.ps1 (Windows) 來啟用環境。當命令提示字元開頭顯示 (.venv) 時,即代表環境已啟用。

建立並執行最小化的 Flask 應用程式

  1. 在 VS Code 中,使用選單中的 File (檔案) > New (新增),按下 Ctrl+N,或使用「檔案總管」檢視中的新增檔案圖示(如下所示),在您的專案資料夾中建立一個名為 app.py 的新檔案。

    Flask tutorial: new file icon in Explorer View

  2. app.py 中,新增匯入 Flask 並建立 Flask 物件實例的程式碼。如果您手動輸入下方的程式碼(而非使用複製貼上),您可以觀察到 VS Code 的 IntelliSense 與自動完成功能。

    from flask import Flask
    app = Flask(__name__)
    
  3. 同樣在 app.py 中,新增一個會傳回內容(在此為簡單字串)的函式,並使用 Flask 的 app.route 裝飾器將 URL 路由 / 對應到該函式。

    @app.route("/")
    def home():
        return "Hello, Flask!"
    

    提示:您可以對同一個函式使用多個裝飾器(每行一個),具體取決於您想要將多少個不同的路由對應到同一個函式。

  4. 儲存 app.py 檔案 (⌘S (Windows, Linux Ctrl+S))。

  5. 在整合式終端機中,輸入 python -m flask run 來執行應用程式,這會啟動 Flask 開發伺服器。開發伺服器預設會尋找 app.py。當您執行 Flask 時,應該會看到類似以下的輸出。

    (.venv) D:\py\\hello_flask>python -m flask run
     * Environment: production
       WARNING: Do not use the development server in a production environment.
       Use a production WSGI server instead.
     * Debug mode: off
     * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
    

    如果您看到找不到 Flask 模組的錯誤,請確保您已依照前一節結尾所述,在虛擬環境中執行了 python -m pip install flask

    此外,如果您想在不同的 IP 位址或連接埠上執行開發伺服器,請使用 host 和 port 命令列引數,例如 --host=0.0.0.0 --port=80

  6. 若要使用預設瀏覽器開啟渲染後的頁面,請在終端機中 Ctrl+點擊 http://127.0.0.1:5000/ 這個 URL。

    Flask tutorial: the running app in a browser

  7. 觀察當您造訪像 / 這樣的 URL 時,偵錯終端機會出現一則顯示 HTTP 請求的訊息。

    127.0.0.1 - - [11/Jul/2018 08:40:15] "GET / HTTP/1.1" 200 -
    
  8. 使用終端機中的 Ctrl+C 停止應用程式。

提示:使用 app.py 以外的檔名(例如 webapp.py)時,您需要定義一個名為 FLASK_APP 的環境變數,並將其值設為您選擇的檔案。Flask 的開發伺服器隨後會使用 FLASK_APP 的值,而不是預設的 app.py 檔案。如需詳細資訊,請參閱 Flask 命令列介面

在偵錯工具中執行應用程式

偵錯讓您有機會在特定程式碼行上暫停正在執行的程式。當程式暫停時,您可以檢查變數、在「偵錯主控台」面板中執行程式碼,並利用偵錯 (Debugging) 中所述的功能。執行偵錯器也會在偵錯工作階段開始前自動儲存任何修改過的檔案。

開始之前:請確保您已使用終端機中的 Ctrl+C 停止了上一節中執行的應用程式。如果您讓應用程式在一個終端機中保持執行,它會繼續佔用該連接埠。結果就是,當您使用相同的連接埠在偵錯器中執行應用程式時,原本正在執行的應用程式會處理所有請求,而您將無法在偵錯中的應用程式看到任何活動,程式也不會在斷點處停止。換句話說,如果偵錯器似乎無法運作,請確保沒有其他應用程式執行個體仍在執行。

  1. app.py 的內容替換為以下程式碼,它新增了第二個路由和函式,您可以在偵錯工具中逐步執行。

    import re
    from datetime import datetime
    
    from flask import Flask
    
    app = Flask(__name__)
    
    
    @app.route("/")
    def home():
        return "Hello, Flask!"
    
    
    @app.route("/hello/<name>")
    def hello_there(name):
        now = datetime.now()
        formatted_now = now.strftime("%A, %d %B, %Y at %X")
    
        # Filter the name argument to letters only using regular expressions. URL arguments
        # can contain arbitrary text, so we restrict to safe characters only.
        match_object = re.match("[a-zA-Z]+", name)
    
        if match_object:
            clean_name = match_object.group(0)
        else:
            clean_name = "Friend"
    
        content = "Hello there, " + clean_name + "! It's " + formatted_now
        return content
    

    用於新 URL 路由 /hello/<name> 的裝飾器定義了一個端點 /hello/,該端點可以接受任何附加值。路由中 <> 內的識別碼定義了一個變數,該變數會傳遞給函式並可在您的程式碼中使用。

    URL 路由區分大小寫。例如,路由 /hello/<name>/Hello/<name> 是不同的。如果您希望同一個函式處理這兩者,請為每個變體使用裝飾器。

    如程式碼註解中所述,請務必過濾使用者提供的任意資訊,以避免對您的應用程式進行各種攻擊。在此情況下,程式碼會過濾 name 引數,使其僅包含字母,從而避免注入控制字元、HTML 等。(當您在下一節中使用模板時,Flask 會進行自動過濾,您將不需要這段程式碼。)

  2. 透過執行下列任一操作,在 hello_there 函式的第一行程式碼 (now = datetime.now()) 設定斷點

    • 將游標置於該行上,按下 F9,或
    • 將游標置於該行上,選取 執行 (Run) > 切換斷點 (Toggle Breakpoint) 功能表命令,或
    • 直接點擊行號左側的邊距(懸停在那裡時會出現一個淡紅色的圓點)。

    斷點會顯示為左側邊距中的一個紅點

    Flask tutorial: a breakpoint set on the first line of the hello_there function

  3. 切換至 VS Code 中的 Run and Debug (執行與偵錯) 檢視(使用左側活動列或 ⇧⌘D (Windows, Linux Ctrl+Shift+D))。您可能會看到「To customize Run and Debug create a launch.json file」(若要自訂執行與偵錯,請建立 launch.json 檔案) 的訊息。這表示您尚未擁有包含偵錯設定的 launch.json 檔案。如果您點擊 create a launch.json file (建立 launch.json 檔案) 連結,VS Code 可以為您建立該檔案。

    Flask tutorial: initial view of the debug panel

  4. 選取該連結,VS Code 將會提示您進行偵錯設定。從下拉式選單中選取 Flask,VS Code 將會以 Flask 執行設定填入一個新的 launch.json 檔案。launch.json 檔案包含許多偵錯設定,每一項都是 configuration 陣列中的獨立 JSON 物件。

  5. 向下捲動並檢查名為 "Python: Flask" 的設定。此設定包含 "module": "flask",,這會指示 VS Code 在啟動偵錯工具時以 -m flask 執行 Python。它還在 env 屬性中定義了 FLASK_APP 環境變數以識別啟動檔案(預設為 app.py),但允許您輕鬆指定其他檔案。如果您想變更主機和/或連接埠,可以使用 args 陣列。

    {
        "name": "Python Debugger: Flask",
        "type": "debugpy",
        "request": "launch",
        "module": "flask",
        "env": {
            "FLASK_APP": "app.py",
            "FLASK_DEBUG": "1"
        },
        "args": [
            "run",
            "--no-debugger",
            "--no-reload"
        ],
        "jinja": true,
        "justMyCode": true
    },
    

    注意:如果您的設定中的 env 項目包含 "FLASK_APP": "${workspaceFolder}/app.py",請將其更改為上述的 "FLASK_APP": "app.py"。否則,您可能會遇到像「Cannot import module C」(其中 C 是專案資料夾所在的磁碟機代號) 之類的錯誤訊息。

    注意:一旦建立 launch.json,編輯器中就會出現 Add Configuration (新增設定) 按鈕。該按鈕會顯示一個清單,列出可新增至設定清單開頭的其他設定。(Run (執行) > Add Configuration (新增設定) 選單指令具有相同的作用。)

  6. 儲存 launch.json (⌘S (Windows, Linux Ctrl+S))。在偵錯設定下拉式清單中,選取 Python: Flask 設定。

    Flask tutorial: selecting the Flask debugging configuration

  7. 選取 執行 (Run) > 開始偵錯 (Start Debugging) 功能表命令,或選取清單旁邊的綠色 開始偵錯 (Start Debugging) 箭頭(F5)來啟動偵錯器

    Flask tutorial: start debugging/continue arrow on the debug toolbar

    觀察狀態列會變色以指示正在偵錯

    Flask tutorial: appearance of the debugging status bar

    偵錯工具列(如下所示)也會出現在 VS Code 中,包含以下順序的指令:暫停(或繼續,F5)、逐步執行 (F10)、進入函式 (F11)、跳出函式 (⇧F11 (Windows, Linux Shift+F11))、重新啟動 (⇧⌘F5 (Windows, Linux Ctrl+Shift+F5)) 以及停止 (⇧F5 (Windows, Linux Shift+F5))。如需每個指令的說明,請參閱 VS Code 偵錯

    Flask tutorial: the VS Code debug toolbar

  8. 輸出會出現在「Python Debug Console (Python 偵錯主控台)」終端機中。在該終端機中 Ctrl+點擊 http://127.0.0.1:5000/ 連結,以在瀏覽器中開啟該 URL。在瀏覽器的網址列中,導覽至 http://127.0.0.1:5000/hello/VSCode。在頁面渲染之前,VS Code 會在您設定的中斷點處暫停程式。中斷點上的黃色小箭頭表示它是下一行要執行的程式碼。

    Flask tutorial: VS Code paused at a breakpoint

  9. 使用「不進入函式」(Step Over) 來執行 now = datetime.now() 陳述式。

  10. 在 VS Code 視窗的左側,您會看到一個 變數 (Variables) 窗格,顯示區域變數(例如 now)以及引數(例如 name)。下方是 監看 (Watch)呼叫堆疊 (Call Stack)斷點 (Breakpoints) 的窗格(詳情請參閱 VS Code 偵錯)。在 區域變數 (Locals) 區段中,嘗試展開不同的值。您也可以雙擊值(或使用 Enter (Windows, Linux F2))來修改它們。不過,更改變數(例如 now)可能會破壞程式。開發人員通常只在程式碼最初未產生正確值時,才會進行更改以修正值。

    Flask tutorial: local variables and arguments in VS Code during debugging

  11. 當程式暫停時,Debug Console (偵錯主控台) 面板(與「終端機」面板中的「Python 偵錯主控台」不同)讓您可以使用程式的當前狀態來測試運算式並嘗試片段程式碼。例如,在您執行過 now = datetime.now() 這一行之後,您可以嘗試不同的日期/時間格式。在編輯器中,選取讀取 now.strftime("%A, %d %B, %Y at %X") 的程式碼,然後按右鍵選取 Evaluate in Debug Console (在偵錯主控台中評估),將該程式碼傳送至偵錯主控台執行。

    now.strftime("%A, %d %B, %Y at %X")
    'Wednesday, 31 October, 2018 at 18:13:39'
    

    提示偵錯主控台還會顯示應用程式內部可能不會出現在終端機中的例外情況。例如,如果您在 執行與偵錯 (Run and Debug) 檢視的 呼叫堆疊 (Call Stack) 區域看到「在例外狀況處暫停」(Paused on exception) 的訊息,請切換至 偵錯主控台以查看例外訊息。

  12. 將該行複製到偵錯主控台底部的 > 提示符中,並嘗試更改格式

    now.strftime("%a, %d %B, %Y at %X")
    'Wed, 31 October, 2018 at 18:13:39'
    now.strftime("%a, %d %b, %Y at %X")
    'Wed, 31 Oct, 2018 at 18:13:39'
    now.strftime("%a, %d %b, %y at %X")
    'Wed, 31 Oct, 18 at 18:13:39'
    
  13. 如果需要,可以逐步執行多幾行程式碼,然後選取「繼續」(Continue) (F5) 讓程式執行。瀏覽器視窗會顯示結果

    Flask tutorial: result of the modified program

  14. 將程式碼中的那一行更改為使用不同的日期時間格式,例如 now.strftime("%a, %d %b, %y at %X"),然後儲存檔案。Flask 伺服器會自動重新載入,這意味著更改將會套用,而無需重新啟動偵錯工具。重新整理瀏覽器上的頁面即可看到更新。

  15. 完成後,關閉瀏覽器並停止偵錯器。若要停止偵錯器,請使用停止工具列按鈕(紅色正方形)或 執行 (Run) > 停止偵錯 (Stop Debugging) 命令(⇧F5 (Windows, Linux Shift+F5))。

提示:為了更方便重複導覽至特定 URL(如 http://127.0.0.1:5000/hello/VSCode),請使用 print 陳述式輸出該 URL。該 URL 會出現在終端機中,您可以在該處使用 Ctrl+點擊 在瀏覽器中開啟它。

「前往定義」(Go to Definition) 和「預覽定義」(Peek Definition) 命令

在使用 Flask 或任何其他程式庫時,您可能會想要檢查這些程式庫本身的程式碼。VS Code 提供了兩個方便的指令,可以直接導覽至任何程式碼中類別和其他物件的定義。

  • Go to Definition (前往定義) 會從您的程式碼跳轉至定義物件的程式碼。例如,在 app.py 中,右鍵點擊 Flask 類別(在 app = Flask(__name__) 這一行中)並選取 Go to Definition (前往定義)(或使用 F12),即可導覽至 Flask 程式庫中的類別定義。

  • 預覽定義 (Peek Definition)⌥F12 (Windows Alt+F12, Linux Ctrl+Shift+F10),也位於右鍵快顯功能表上)類似,但會直接在編輯器中顯示類別定義(在編輯器視窗中騰出空間,以免遮擋任何程式碼)。按下 Escape 關閉預覽視窗,或使用右上角的 x

    Flask tutorial: peek definition showing the Flask class inline

使用範本來轉譯頁面

到目前為止,您在此教學課程中建立的應用程式僅能從 Python 程式碼產生純文字網頁。雖然可以直接在程式碼中產生 HTML,但開發人員通常會避免這種做法,因為這會使應用程式面臨跨網站指令碼 (XSS) 攻擊。例如,在本教學課程的 hello_there 函式中,有人可能會想用類似 content = "<h1>Hello there, " + clean_name + "!</h1>" 的方式在程式碼中格式化輸出,並將 content 中的結果直接傳送給瀏覽器。這種開放性使攻擊者能夠將惡意的 HTML(包括 JavaScript 程式碼)放入 URL 中,最終進入 clean_name,從而在瀏覽器中執行。

一個更好的做法是完全不將 HTML 放入您的程式碼中,而是使用範本 (templates),這樣您的程式碼只關注資料值,而不關注轉譯。

  • 模板是一個 HTML 檔案,其中包含程式碼在執行階段所提供值的預留位置。模板引擎會在渲染頁面時處理替換工作。因此,程式碼僅需關注資料值,而模板僅需關注標記。
  • Flask 的預設模板引擎是 Jinja,它會在您安裝 Flask 時自動安裝。該引擎提供了靈活的選項,包括自動逸出(以防止 XSS 攻擊)和模板繼承。透過繼承,您可以定義一個具有通用標記的基礎頁面,然後在該基礎上進行頁面特定的擴充。

在本節中,您將使用模板建立一個單頁。在接下來的章節中,您將設定應用程式以提供靜態檔案,然後為應用程式建立多個頁面,每個頁面都包含來自基礎模板的導覽列。

  1. hello_flask 資料夾內,建立一個名為 templates 的資料夾,這是 Flask 預設搜尋模板的地方。

  2. templates 資料夾中,建立一個名為 hello_there.html 的檔案,內容如下。此模板包含兩個名為「name」和「date」的預留位置,它們由成對的大括號 {{}} 界定。如您所見,您也可以直接在模板中包含格式化程式碼。

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8" />
            <title>Hello, Flask</title>
        </head>
        <body>
            {%if name %}
                <strong>Hello there, {{ name }}!</strong> It's {{ date.strftime("%A, %d %B, %Y at %X") }}.
            {% else %}
                What's your name? Provide it after /hello/ in the URL.
            {% endif %}
        </body>
    </html>
    

    提示:Flask 開發人員通常使用 flask-babel 擴充功能來進行日期格式化,而不是 strftime,因為 flask-babel 會考慮地區設定和時區。

  3. app.py 中,在檔案頂部附近匯入 Flask 的 render_template 函式。

    from flask import render_template
    
  4. 同樣在 app.py 中,修改 hello_there 函式以使用 render_template 來載入模板並套用具名值(並新增一個路由來識別沒有名稱的情況)。render_template 假設第一個引數相對於 templates 資料夾。通常,開發人員會將模板命名為與使用它們的函式相同的名稱,但並不要求名稱必須相符,因為您總是在程式碼中參照確切的檔案名稱。

    @app.route("/hello/")
    @app.route("/hello/<name>")
    def hello_there(name = None):
        return render_template(
            "hello_there.html",
            name=name,
            date=datetime.now()
        )
    

    您可以看到程式碼現在簡單得多,並且只關注資料值,因為標記和格式化都包含在範本中。

  5. 啟動程式(在偵錯器內部或外部,使用 ⌃F5 (Windows, Linux Ctrl+F5)),導覽至 /hello/name URL,並觀察結果。

  6. 此外,嘗試使用像 <a%20value%20that%20could%20be%20HTML> 這樣的名稱導覽至 /hello/name URL,看看 Flask 自動逸出的效果。「name」值在瀏覽器中會顯示為純文字,而不是渲染成實際的元素。

提供靜態檔案

靜態檔案有兩種類型。第一種是像樣式表這樣的檔案,頁面模板可以直接參照它們。這類檔案可以放在應用程式中的任何資料夾,但通常放在 static 資料夾內。

第二種類型是您希望在程式碼中定址的檔案,例如當您想要實作一個傳回靜態檔案的 API 端點時。為此,Flask 物件包含一個內建方法 send_static_file,它會產生一個包含應用程式 static 資料夾內靜態檔案的回應。

以下章節將示範這兩種型態的靜態檔案。

在範本中引用靜態檔案

  1. hello_flask 資料夾中,建立一個名為 static 的資料夾。

  2. static 資料夾內,建立一個名為 site.css 的檔案,內容如下。輸入此程式碼後,請觀察 VS Code 為 CSS 檔案提供的語法反白顯示,包括顏色預覽。

    .message {
        font-weight: 600;
        color: blue;
    }
    
  3. templates/hello_there.html 中,於 </head> 標籤前加入以下行,以建立對樣式表的參照。

    <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='site.css')}}" />
    

    此處使用的 Flask url_for 標籤會建立指向該檔案的正確路徑。由於它接受變數作為引數,如果需要,url_for 允許您以程式設計方式控制產生的路徑。

  4. 同樣在 templates/hello_there.html 中,將 <body> 元素的內容替換為以下標記,該標記使用 message 樣式而不是 <strong> 標籤(並且在您僅使用 hello/ URL 而未提供名稱時也會顯示訊息)。

    {%if name %}
        <span class="message">Hello there, {{ name }}!</span> It's {{ date.strftime("%A, %d %B, %Y at %X") }}.
    {% else %}
        <span class="message">What's your name? Provide it after /hello/ in the URL.</span>
    {% endif %}
    
  5. 執行應用程式,導覽至 /hello/name URL,並觀察訊息以藍色呈現。完成後停止應用程式。

從程式碼提供靜態檔案
  1. static 資料夾中,建立一個名為 data.json 的 JSON 資料檔案,內容如下(這些是無意義的範例資料)。

    {
      "01": {
        "note": "This data is very simple because we're demonstrating only the mechanism."
      }
    }
    
  2. app.py 中,新增一個具有 /api/data 路由的函式,並使用 send_static_file 方法傳回該靜態資料檔案。

    @app.route("/api/data")
    def get_data():
        return app.send_static_file("data.json")
    
  3. 執行應用程式並導覽至 /api/data 端點,即可看到靜態檔案已傳回。完成後請停止應用程式。

建立多個繼承自基礎範本的範本

由於大多數 Web 應用程式不只一個頁面,且這些頁面通常共用許多共同元素,因此開發人員會將這些共同元素分離成一個基礎頁面模板,其他頁面模板隨後可以進行擴充(這也稱為模板繼承)。

此外,由於您可能會建立許多延伸相同範本的頁面,因此在 VS Code 中建立一個程式碼片段 (code snippet) 以便快速初始化新的頁面範本會很有幫助。程式碼片段可協助您避免繁瑣且易於出錯的複製貼上操作。

下列各節將引導您完成此過程的不同部分。

建立基礎頁面範本與樣式

Flask 中的基礎頁面模板包含一組頁面中所有共用的部分,包括對 CSS 檔案、指令碼檔案等的參照。基礎模板還定義了一個或多個 block 標籤,期望繼承該基礎的其他模板能對其進行覆寫。區塊標籤在基礎模板和延伸模板中都由 {% block <name> %}{% endblock %} 界定。

下列步驟示範建立基礎範本。

  1. templates 資料夾中,建立一個名為 layout.html 的檔案,內容如下,其中包含名為「title」和「content」的區塊。如您所見,該標記定義了一個簡單的導覽列結構,連結至您稍後將建立的 Home、About 和 Contact 頁面。每個連結再次使用 Flask 的 url_for 標籤,以便在執行階段為對應的路由產生連結。

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8" />
            <title>{% block title %}{% endblock %}</title>
            <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='site.css')}}" />
        </head>
    
        <body>
            <div class="navbar">
                <a href="{{ url_for('home') }}" class="navbar-brand">Home</a>
                <a href="{{ url_for('about') }}" class="navbar-item">About</a>
                <a href="{{ url_for('contact') }}" class="navbar-item">Contact</a>
            </div>
    
            <div class="body-content">
                {% block content %}
                {% endblock %}
                <hr/>
                <footer>
                    <p>&copy; 2018</p>
                </footer>
            </div>
        </body>
    </html>
    
  2. 將以下樣式新增至 static/site.css,位於現有的「message」樣式下方,並儲存檔案。請注意,本教學不打算示範響應式設計;這些樣式只是產生一個看起來還不錯的結果。

    .navbar {
        background-color: lightslategray;
        font-size: 1em;
        font-family: 'Trebuchet MS', 'Lucida Sans Unicode', 'Lucida Grande', 'Lucida Sans', Arial, sans-serif;
        color: white;
        padding: 8px 5px 8px 5px;
    }
    
    .navbar a {
        text-decoration: none;
        color: inherit;
    }
    
    .navbar-brand {
        font-size: 1.2em;
        font-weight: 600;
    }
    
    .navbar-item {
        font-variant: small-caps;
        margin-left: 30px;
    }
    
    .body-content {
        padding: 5px;
        font-family:'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
    }
    

您可以此時執行應用程式,但因為您還沒有在任何地方使用該基礎範本,也沒有更改任何程式碼檔案,所以結果與上一步相同。請完成剩餘的章節以查看最終效果。

建立程式碼片段

由於您在下一節中建立的三個頁面都將延伸 layout.html,因此建立一個 程式碼片段 來初始化帶有對基礎範本適當引用的新範本檔案可以節省時間。程式碼片段從單一來源提供一致的程式碼片段,這避免了在使用現有程式碼進行複製貼上時可能產生的錯誤。

  1. 在 VS Code 中,選取 File (檔案) > Preferences (喜好設定) > Configure User Snippets (設定使用者程式碼片段)

  2. 在出現的清單中,選取 html。如果您之前曾建立過程式碼片段,該選項可能會出現在清單的 Existing Snippets (現有程式碼片段) 區段中,顯示為 "html.json"。

  3. VS Code 開啟 html.json 後,在現有的大括號內新增以下條目(此處未顯示解釋性註解,它們描述了詳細資訊,例如 $0 行如何指示 VS Code 在插入程式碼片段後將游標放置於何處)。

    "Flask Tutorial: template extending layout.html": {
        "prefix": "flextlayout",
        "body": [
            "{% extends \"layout.html\" %}",
            "{% block title %}",
            "$0",
            "{% endblock %}",
            "{% block content %}",
            "{% endblock %}"
        ],
    
        "description": "Boilerplate template that extends layout.html"
    },
    
  4. 儲存 html.json 檔案 (⌘S (Windows, Linux Ctrl+S))。

  5. 現在,每當您開始輸入程式碼片段的前綴(例如 flext)時,VS Code 就會將該程式碼片段作為自動完成選項提供,如下一節所示。您也可以使用 Insert Snippet (插入程式碼片段) 指令從選單中選擇程式碼片段。

有關程式碼片段的更多資訊,請參閱 建立程式碼片段 (Creating snippets)

使用程式碼片段新增頁面

有了程式碼片段,您就可以快速建立首頁 (Home)、關於 (About) 和聯絡 (Contact) 頁面的範本。

  1. templates 資料夾中,建立一個名為 home.html 的新檔案。然後開始輸入 flext,即可看到程式碼片段作為完成選項出現。

    Flask tutorial: autocompletion for the flextlayout code snippet

    當您選取該完成項時,程式碼片段的內容會出現,游標位於片段的插入點

    Flask tutorial: insertion of the flextlayout code snippet

  2. 在「title」區塊的插入點,寫入 Home;在「content」區塊中,寫入 <p>Home page for the Visual Studio Code Flask tutorial.</p>,然後儲存檔案。這些行是延伸頁面模板中唯一獨特的部分。

  3. templates 資料夾中建立 about.html,使用該程式碼片段插入樣板標記,在「title」和「content」區塊中分別插入 About us<p>About page for the Visual Studio Code Flask tutorial.</p>,然後儲存檔案。

  4. 重複上述步驟,使用 Contact us<p>Contact page for the Visual Studio Code Flask tutorial.</p> 在兩個內容區塊中建立 templates/contact.html

  5. app.py 中,為 /about/ 和 /contact/ 路由新增函式,分別參照其各自的頁面模板。同時修改 home 函式以使用 home.html 模板。

    # Replace the existing home function with the one below
    @app.route("/")
    def home():
        return render_template("home.html")
    
    # New functions
    @app.route("/about/")
    def about():
        return render_template("about.html")
    
    @app.route("/contact/")
    def contact():
        return render_template("contact.html")
    

執行應用程式

在所有頁面模板就緒後,儲存 app.py,執行應用程式,並開啟瀏覽器查看結果。在頁面之間導覽,以驗證頁面模板是否正確地繼承了基礎模板。

Flask tutorial: app rendering a common nav bar from the base template

注意:如果您沒有看到最新的變更,您可能需要對頁面進行強制重新整理,以避免看到快取檔案。

選做活動

下列各節描述了您在使用 Python 和 Visual Studio Code 時可能會覺得有幫助的其他步驟。

為環境建立 requirements.txt 檔案

當您透過原始碼控制或其他方式共用應用程式程式碼時,複製虛擬環境中的所有檔案是沒有意義的,因為接收者總是可以自行重建該環境。

因此,開發人員通常會從原始碼控制中省略虛擬環境資料夾,並改用 requirements.txt 檔案來描述應用程式的依賴項目。

雖然您可以手動建立該檔案,但您也可以使用 pip freeze 命令,根據已啟動環境中實際安裝的程式庫來產生該檔案

  1. 使用 Python: 選取解譯器 (Python: Select Interpreter) 命令選取您選擇的環境,執行 終端機: 建立新終端機 (Terminal: Create New Terminal) 命令 (⌃⇧` (Windows, Linux Ctrl+Shift+`))) 以開啟一個已啟動該環境的終端機。

  2. 在終端機中,執行 pip freeze > requirements.txt 以在您的專案資料夾中建立 requirements.txt 檔案。

任何收到專案複本的人(或任何建置伺服器)只需執行 pip install -r requirements.txt 指令,即可在原始環境中重新安裝套件。(不過,接收者仍需建立自己的虛擬環境。)

注意pip freeze 會列出您在目前環境中安裝的所有 Python 套件,包括您目前未使用的套件。該命令還會列出具有精確版本號的套件,您可能希望將其轉換為範圍以在未來獲得更多彈性。有關詳細資訊,請參閱 pip 命令文件中的 需求檔案 (Requirements Files)

重構專案以支援進一步開發

在本 Flask 教學課程中,所有應用程式程式碼都包含在單一 app.py 檔案中。為了允許進一步開發並分離關注點,將 app.py 的片段重構為獨立的檔案會很有幫助。

  1. 在您的專案資料夾中,為應用程式建立一個資料夾,例如 hello_app,以將其檔案與其他專案層級的檔案(如 requirements.txt 以及 VS Code 儲存設定和偵錯設定檔的 .vscode 資料夾)分離。

  2. statictemplates 資料夾移至 hello_app 中,因為這些資料夾必然包含應用程式程式碼。

  3. hello_app 資料夾中,建立一個名為 views.py 的檔案,其中包含路由和檢視函式。

    from flask import Flask
    from flask import render_template
    from datetime import datetime
    from . import app
    
    @app.route("/")
    def home():
        return render_template("home.html")
    
    @app.route("/about/")
    def about():
        return render_template("about.html")
    
    @app.route("/contact/")
    def contact():
        return render_template("contact.html")
    
    @app.route("/hello/")
    @app.route("/hello/<name>")
    def hello_there(name = None):
        return render_template(
            "hello_there.html",
            name=name,
            date=datetime.now()
        )
    
    @app.route("/api/data")
    def get_data():
        return app.send_static_file("data.json")
    
  4. hello_app 資料夾中,建立一個內容如下的 __init__.py 檔案。

    import flask
    app = flask.Flask(__name__)
    
  5. hello_app 資料夾中,建立一個內容如下的 webapp.py 檔案。

    # Entry point for the application.
    from . import app    # For application discovery by the 'flask' command.
    from . import views  # For import side-effects of setting up routes.
    
  6. 開啟偵錯設定檔 launch.json 並更新 env 屬性如下,以指向啟動物件。

    "env": {
        "FLASK_APP": "hello_app.webapp"
    },
    
  7. 刪除專案根目錄中原始的 app.py 檔案,因為其內容已移至其他應用程式檔案中。

  8. 您的專案結構現在應該類似於以下內容:

    Flask tutorial: modified project structure with separate files and folders for parts of the app

  9. 再次在偵錯工具中執行應用程式,以確保一切運作正常。若要在 VS Code 偵錯工具之外執行應用程式,請從終端機使用下列步驟:

    1. FLASK_APP 設定環境變數。在 Linux 和 macOS 上,使用 export set FLASK_APP=webapp;在 Windows 上,如果您使用 PowerShell,請使用 $env:FLASK_APP=webapp,或者如果您使用命令提示字元,請使用 set FLASK_APP=webapp
    2. 導覽至 hello_app 資料夾,然後使用 python -m flask run 啟動程式。

使用 Container Tools 擴充功能為 Flask 應用程式建立容器

Container Tools 擴充功能 讓您可以輕鬆地從 Visual Studio Code 建置、管理和部署容器化應用程式。如果您有興趣了解如何為本教學課程中開發的 Flask 應用程式建立 Python 容器,請查看容器中的 Python (Python in a container) 教學課程,該教學課程將引導您完成如何進行以下操作:

  • 建立描述簡單 Python 容器的 Dockerfile 檔案。
  • 建置、執行並驗證 Flask 應用程式的功能。
  • 對在容器中執行的應用程式進行偵錯。

如果您遇到任何問題,可以在 Python 擴充功能討論問答 (Discussions Q&A) 中搜尋解答或提問。

後續步驟

恭喜您完成本次在 Visual Studio Code 中使用 Flask 的教學導覽!

本教學課程的完整程式碼專案可在 GitHub 上找到:python-sample-vscode-flask-tutorial

由於本教學課程僅觸及了頁面模板的皮毛,有關模板的更多資訊,請參閱 Jinja2 文件模板設計者文件 (Template Designer Documentation) 包含了模板語言的所有細節。您可能還會想複習 Flask 官方教學課程 以及 Flask 擴充功能 的相關文件。

若要嘗試在正式環境網站上執行您的應用程式,請查看教學課程 使用 Docker 容器將 Python 應用程式部署到 Azure App Service (Deploy Python apps to Azure App Service using Docker Containers)。Azure 還提供了一個標準容器,Linux 上的 App Service (App Service on Linux),您可以在其中從 VS Code 部署 Web 應用程式。

您可能還會想要審閱 VS Code 文件中與 Python 相關的下列文章

© . This site is unofficial and not affiliated with Microsoft.