步驟 2:使用檢視與頁面範本建立 Django 應用程式

上一個步驟:建立 Visual Studio 專案和解決方案

在 Visual Studio 專案中,您現在只有 Django 專案的網站層級元件,其可執行一或多個 Django 應用程式。 下一個步驟是建立您第一個具有單一網頁的應用程式。

在這個步驟中,您將了解如何:

  • 建立具有單一網頁的 Django 應用程式 (步驟 2-1)
  • 從 Django 專案執行應用程式 (步驟 2-2)
  • 使用 HTML 轉譯檢視 (步驟 2-3)
  • 使用 Django 頁面範本轉譯檢視 (步驟 2-4)

步驟 2-1:建立具有預設結構的應用程式

Django 應用程式是個別的 Python 套件,其中包含具特定用途的相關檔案集。 Django 專案可以包含許多應用程式,可協助 Web 主機從單一網域名稱提供許多個別的進入點。 例如,適用於像是 contoso.com 之網域的 Django 專案,可能會針對 www.contoso.com 包含一個應用程式、針對 support.contoso.com 包含第二個應用程式,針對 docs.contoso.com 包含第三個應用程式。 在此情況下,Django 專案會處理網站層級 URL 路由和設定 (在其 urls.pysettings.py 檔案中)。 每個應用程式都有自己的不同樣式和行為,透過其內部路由、檢視、模型、靜態檔案和系統管理介面。

Django 應用程式通常會以一組標準的檔案作為開始。 Visual Studio 提供範本以初始化 Django 專案內的 Django 應用程式,並提供具相同用途的整合式功能表命令:

  • 範本:在 [方案總管] 中,以滑鼠右鍵按一下專案,然後選取 [加入]>[新項目]。 在 [加入新項目] 對話方塊中,選取 [Django 1.9 應用程式] 範本,在 [名稱] 欄位中指定應用程式名稱,然後選取 [加入]

Screenshot of Solution Explorer.

Screenshot of Add New Item window.

  • 整合式命令:在 [方案總管] 中,以滑鼠右鍵按一下專案,然後選取 [加入]>[Django 應用程式]。 此命令會提示您輸入名稱。 在 [新應用程式名稱] 欄位中指定應用程式名稱,然後選取 [確定]

    Menu command for adding a Django app.

    Menu command to enter a Django app name.

使用任一種方法來建立名為 "HelloDjangoApp" 的應用程式。 現在,您的專案中會建立 "HelloDjangoApp" 資料夾。 資料夾包含下列項目:

Django app files in Solution Explorer.

項目 說明
移轉 Django 儲存指令碼的資料夾,這些指令碼會更新資料庫以配合對模型所做的變更。 接著,Django 的移轉工具會對任何舊版資料庫套用必要的變更,以使它符合目前的模型。 透過使用移轉,您可以專注於模型上,並讓 Django 處理基礎資料庫結構描述。 Django 文件中會討論移轉。 目前,資料夾包含 __init__.py 檔案 (表示資料夾定義自己的 Python 封裝)。
__init__.py 此檔案會將應用程式識別為套件。
templates Django 頁面範本的資料夾,其中包含單一 index.html 檔案。 index.html 檔案會放在與應用程式名稱相同的資料夾中。 (在 Visual Studio 2017 15.7 與更舊版本中,該檔案會直接放置在 templates 下,而步驟 2-4 會指示您建立子資料夾。)範本是 HTML 的區塊,檢視可在其中加入資訊,以動態呈現頁面。 頁面範本「變數」(例如 index.html 中的 {{ content }}) 是動態值的預留位置,如本文稍後所述 (步驟 2)。 Django 應用程式通常會將其範本放置在名稱與應用程式名稱相符的子資料夾中,來為其範本建立命名空間。
admin.py 在您延伸應用程式系統管理介面的 Python 檔案,用來檢視和編輯資料庫中的資料。 此檔案一開始只包含陳述式 from django.contrib import admin。 依預設,Django 會透過 Django 專案 settings.py 檔案中的項目來包含標準系統管理介面。 若要開啟介面,您可以在 urls.py 檔案中取消註解現有的項目。
apps.py Python 檔案,定義應用程式的設定類別 (請參閱本表後面的內容)。
models.py 模型是依函式識別的資料物件,檢視會透過它和應用程式基礎資料庫互動。 Django 提供資料庫連線層,使得應用程式本身不需要處理模型詳細資料。 models.py 檔案是您建立模型的預設位置。 models.py 檔案一開始只包含 from django.db import models 陳述式。
tests.py Python 檔案,包含單元測試的基本結構。
views.py 檢視類似於網頁,其會取得 HTTP 要求並傳回 HTTP 回應。 檢視通常會以 HTML 形式轉譯,而網頁瀏覽器會知道如何顯示,但檢視不一定需要顯示出來 (例如中繼形式)。 檢視是由 Python 函式定義,其負責轉譯 HTML 至瀏覽器。 views.py 檔案是您建立檢視的預設位置。 views.py 檔案一開始只包含 from django.shortcuts import render 陳述式。

使用名稱 "HelloDjangoApp" 時,apps.py 檔案的內容會顯示為:

from django.apps import AppConfig

class HelloDjangoAppConfig(AppConfig):
    name = 'HelloDjango'

問題:在 Visual Studio 中建立 Django 應用程式,和在命令列上建立應用程式有何不同?

回答:執行 [加入]>[Django 應用程式] 命令,或搭配 Django 應用程式範本使用 [加入]>[新項目] 所產生的檔案,和 Django 命令 manage.py startapp <app_name> 相同。 在 Visual Studio 中建立應用程式的優點,在於應用程式資料夾與其所有檔案都會自動整合在專案中。 您可以使用相同的 Visual Studio 命令,在專案中建立任何數目的應用程式。

步驟 2-2:從 Django 專案執行應用程式

此時,如果您在 Visual Studio 中再次執行專案 (使用工具列按鈕或 [偵錯]> [開始偵錯]),將仍會看到預設頁面。 之所以未出現任何應用程式內容,是因為您必須定義應用程式特定頁面,並將應用程式新增至 Django 專案:

  1. HelloDjangoApp 資料夾中,修改 views.py 檔案,以定義名為 "index" 的檢視:

    from django.shortcuts import render
    from django.http import HttpResponse
    
    def index(request):
        return HttpResponse("Hello, Django!")
    
  2. BasicProject 資料夾中 (在步驟 1 中建立),修改 urls.py 檔案以符合下列程式碼 (如有需要,您可以保留指示性註解):

    from django.urls import include, re_path
    import HelloDjangoApp.views
    
    # Django processes URL patterns in the order they appear in the array
    urlpatterns = [
        re_path(r'^$', HelloDjangoApp.views.index, name='index'),
        re_path(r'^home$', HelloDjangoApp.views.index, name='home')
    ]
    

    每個 URL 模式都會描述 Django 路由傳送特定網站相對 URL (也就是 https://www.domain.com/ 後面的部分) 的檢視。 urlPatterns 中以規則運算式 ^$ 為開頭的第一個項目,就是網站根目錄的路由 ("/")。 第二個項目 ^home$會特別路由 "/home"。 您可以將多個路由傳送至相同的檢視。

  3. 再次執行專案,會看到如檢視所定義的訊息 Hello, Django!。 完成時,請停止伺服器。

認可至原始檔控制

對程式碼進行變更並成功測試之後,您可以檢閱並認可至原始檔控制。 在稍後的步驟中,當本教學課程提醒您再次認可原始檔控制時,您可以參閱本節。

  1. 選取位於 Visual Studio 底部的變更按鈕 (下面圈起處),這會瀏覽至 [Team Explorer]

    Source control changes button on the Visual Studio status bar.

  2. 在 [Team Explorer] 中,輸入像是「建立初始 Django 應用程式」的認可訊息,然後選取 [全部認可]。 當認可完成時,您會看到下列訊息:認可於本機建立的 <雜湊>。同步以將您的變更與伺服器共用。如果您想要將變更推送至遠端存放庫,請選取 [同步],然後選取 [傳出的認可] 底下的 [推送]。 您也可以在累積多個本機認可之後,再推送至遠端。

    Push commits to remote repository in Team Explorer.

問題:路由字串前方的 'r' 前置詞有什麼用途?

回答:Python 中字串上的 'r' 前置詞表示「未經處理」,這會指示 Python 不逸出字串內的任何字元。 規則運算式使用許多特殊字元。 使用 'r' 前置詞可讓字串比逸出字元 '\' 更容易閱讀。

問題:URL 路由項目中 ^ 與 $ 字元的意義為何?

答案:在定義 URL 模式的規則運算式中,^ 表示「行的開頭」,而 $ 則表示「行的結尾」,其中的 URL 是相對於網站根目錄 (https://www.domain.com/ 後面的部分)。 規則運算式 ^$ 實際上表示「空白」,且會比對完整的 URL https://www.domain.com/ (不會將任何內容加入至網站根目錄)。 模式 ^home$ 會完全符合 https://www.domain.com/home/。 (Django 在模式比對中不會使用尾端的 /)。

如果您不在規則運算式中使用尾端的 $ (如同 ^home),URL 模型將會符合以 "home" 開頭的任何 URL,例如 "home"、"homework"、"homestead" 及 "home192837"。

若要使用不同的規則運算式進行實驗,請嘗試使用如 pythex.org \(英文\) 的 regex101.com \(英文\) 等線上工具。

步驟 2-3:使用 HTML 轉譯檢視

您在 views.py 檔案中所擁有的 index 函式會為頁面產生純文字 HTTP 回應。 大多數真實世界的網頁都是以通常含有即時資料的豐富 HTML 網頁來回應。 確實,使用函式來定義檢視的主要原因是為了動態產生內容。

由於 HttpResponse 的引數只是字串,您可以視需要在字串內建置任何 HTML。 做為簡單範例,請將 index 函式取代為下列程式碼 (保留現有的 from 陳述式)。 index 函式接著會使用每次重新整理頁面時會更新的動態內容來產生 HTML 回應。

from datetime import datetime

def index(request):
    now = datetime.now()

    html_content = "<html><head><title>Hello, Django</title></head><body>"
    html_content += "<strong>Hello Django!</strong> on " + now.strftime("%A, %d %B, %Y at %X")
    html_content += "</body></html>"

    return HttpResponse(html_content)

現在,再次執行專案,會看到類似 "Hello Django! on Monday 16 April 2018 at 16:28:10" 的訊息。 重新整理網頁以更新時間,並確認內容會隨每個要求產生。 完成時,請停止伺服器。

提示

停止和重新啟動專案的捷徑,可使用 [偵錯]>[重新啟動] 功能表命令 (Ctrl+Shift+F5),或是偵錯工具列上的 [重新啟動] 按鈕:

Restart button on the debugging toolbar in Visual Studio.

步驟 2-4:使用頁面範本轉譯檢視

以程式碼產生 HTML 適用於小型頁面。 不過,隨著頁面變得更複雜,您必須將頁面的靜態 HTML 元件 (以及 CSS 和 JavaScript 檔案的參考) 維護為「頁面範本」。接著,您可以將動態程式碼產生的內容插入頁面範本。 在上一節中,只有 now.strftime 呼叫中的日期與時間是動態的,這表示您可將所有其他內容置於頁面範本中。

Django 頁面範本是 HTML 的區塊,其中包含多個稱為「變數」的取代權杖。變數會以 {{}} 來劃定,例如 {{ content }}。 然後,Django 的範本模組會以您在程式碼中提供的動態內容取代變數。

下列步驟示範如何使用頁面範本:

  1. 在包含 Django 專案的 BasicProject 資料夾下,開啟 settings.py 檔案。 將應用程式名稱 "HelloDjangoApp" 新增至 INSTALLED_APPS 清單。 將應用程式新增至清單,能告知 Django 專案具有 "HelloDjangoApp" 名稱的資料夾中包含應用程式:

    INSTALLED_APPS = [
        'HelloDjangoApp',
        # Other entries...
    ]
    
  2. settings.py 檔案中,確保 TEMPLATES 物件包含下列這一行 (預設包含)。 下列程式碼會指示 Django 在已安裝應用程式的 templates 資料夾中尋找範本:

    'APP_DIRS': True,
    
  3. HelloDjangoApp 資料夾中,開啟 templates/HelloDjangoApp/index.html 頁面範本檔案 (在 VS 2017 15.7 中則為 templates/index.html),就會看到其中包含一個變數 {{ content }}

    <html>
      <head>
        <title></title>
      </head>
    
      <body>
        {{ content }}
      </body>
    </html>
    
  4. HelloDjangoApp 資料夾中,開啟 views.py 檔案,並以使用 django.shortcuts.render 協助程式函式的下列程式碼來取代 index 函式。 render 協助程式能提供處理頁面範本的簡化介面。 確保您保留所有現有的 from 陳述式。

    from django.shortcuts import render   # Added for this step
    
    def index(request):
        now = datetime.now()
    
        return render(
            request,
            "HelloDjangoApp/index.html",  # Relative path from the 'templates' folder to the template file
            # "index.html", # Use this code for VS 2017 15.7 and earlier
            {
                'content': "<strong>Hello Django!</strong> on " + now.strftime("%A, %d %B, %Y at %X")
            }
        )
    

    render 的第一個引數是要求物件,而後面接著的則是應用程式 templates 資料夾內範本檔案的相對路徑。 在適當的情況下,範本檔案會以其所支援的檢視為名。 針對 render 的第三個引數,是範本所參考變數的字典。 您可以在字典中包含物件,在該情況下,範本中的變數可以參考 {{ object.property }}

  5. 執行專案,並觀察輸出結果。 您應該會看到和步驟 2-2 類似的訊息,表示範本運作正常。

    觀察在 content 屬性中使用的 HTML 只會轉譯為純文字,原因是 render 函式會自動逸出該 HTML。 自動逸出可防止意外的插入式攻擊弱點。 開發人員通常會從某個頁面收集輸入,並透過範本預留位置,將其作為另一個頁面的值使用。 逸出也可作為一種提醒,就是最好將 HTML 放在頁面範本中且在程式碼外。 此外,在需要的情況下建立更多變數也很簡單。 例如,變更 index.html 檔案的 templates,以符合下列標記。 下列標記會新增頁面標題,並保留頁面範本中的所有格式設定:

    <html>
      <head>
        <title>{{ title }}</title>
      </head>
      <body>
        <strong>{{ message }}</strong>{{ content }}
      </body>
    </html>
    

    接著,若要為頁面範本中的所有變數提供值,請以下列方式撰寫 index 檢視函式:

    def index(request):
        now = datetime.now()
    
        return render(
            request,
            "HelloDjangoApp/index.html",  # Relative path from the 'templates' folder to the template file
            # "index.html", # Use this code for VS 2017 15.7 and earlier
            {
                'title' : "Hello Django",
                'message' : "Hello Django!",
                'content' : " on " + now.strftime("%A, %d %B, %Y at %X")
            }
        )
    
  6. 停止伺服器並重新啟動專案。 確保頁面會正確轉譯:

    Running app using the template.

  7. Visual Studio 2017 版本 15.7 和更早版本:做為最後一個步驟,將您的範本移至與應用程式名稱相同的子資料夾中。 子資料夾會建立命名空間,並避免與您可能新增至專案的其他應用程式發生潛在衝突。 (VS 2017 15.8+ 中的範本會自動為您執行這個動作。)也就是說,在名為 HelloDjangoApptemplates 中建立子資料夾,將 index.html 檔案移至該子資料夾,然後修改 index 檢視函式。 index 檢視函式會參考範本的新路徑,HelloDjangoApp/index.html。 接著執行專案,確認頁面轉譯正確,然後停止伺服器。

  8. 將變更認可至原始檔控制,並視需要更新遠端存放庫,如步驟 2-2 所述。

問題:頁面範本是否一定要位於個別檔案中?

答案:範本通常會在不同的 HTML 檔案中維護。 您也可以使用內嵌範本。 若要在標記和程式碼之間維持清楚的分隔,建議您使用個別的檔案。

問題:範本必須使用 .html 副檔名嗎?

答案:頁面範本檔案的 .html 副檔名完全是選用的,因為您一定會在 render 函式的第二個引數中識別該檔案的確切相對路徑。 不過,Visual Studio (與其他編輯器) 會提供程式碼完成和針對 .html 檔案的語法色彩等功能,其重要性超過頁面範本嚴格上並不是 HTML 的事實。

實際上,當您在處理 Django 專案時,Visual Studio 會自動偵測到 HTML 檔案是 Django 範本,然後提供一些自動完成功能。 例如,當您開始輸入 Django 頁面範本註解 ({#) 時,Visual Studio 會自動提供結尾的 #} 字元。 [註解選取範圍] 與 [取消註解選取範圍] 命令 (位在 [編輯]> [進階] 功能表和工具列上) 也會使用範本註解,而不是 HTML 註解。

問題:當我執行專案時,看到找不到範本的錯誤。 有什麼問題?

答案:如果您看到找不到範本的錯誤,請確定已將應用程式新增至 Django 專案位於 INSTALLED_APPS 清單的 settings.py 中。 若沒有該項目,Django 就不知道要查看應用程式的 templates 資料夾。

問題:為什麼範本命名空間如此重要?

答案:當 Django 尋找在 render 函式中參考的範本時,它會使用符合相對路徑的第一個檔案。 如果您在相同專案中有多個 Django 應用程式,且專案範本都使用相同的資料夾結構,很可能會有應用程式不小心用到另一個應用程式的範本。 若要避免發生這類錯誤,請一律在應用程式的 templates 資料夾下建立與應用程式名稱相符的子資料夾,以避免任何重複情況。

下一步

深入了解