步驟 3:提供靜態檔案、新增頁面,並將範本繼承與 Django 應用程式搭配使用

上一個步驟:使用檢視與頁面範本來建立 Django 應用程式

在本教學課程的先前步驟中,您已學會如何建立具有單一 HTML 頁面的最小 Django 應用程式。 不過,新式 Web 應用程式包含許多頁面。 新式 Web 頁面會使用共用資源 (例如 CSS 和 JavaScript 檔案),以提供一致的樣式和行為。

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

  • 使用 Visual Studio 項目範本,為可重複使用的程式碼 (步驟 3-1) 新增不同類型的檔案
  • 設定 Django 專案以提供靜態檔案 (步驟 3-2)
  • 將額外頁面加入應用程式 (步驟 3-3)
  • 使用範本繼承,以建立跨頁面使用的標題和瀏覽列 (步驟 3-4)

步驟 3-1:熟悉項目範本

當您開發 Django 應用程式時,通常會加入許多 Python、HTML、CSS 和 JavaScript 檔案。 針對每一種檔案類型 (以及部署可能需要的檔案,例如 web.config),Visual Studio 都提供方便您著手的項目範本

若要檢視可用的範本,請移至 [方案總管],以滑鼠右鍵按一下您要建立項目的資料夾,然後選取 [新增]>[新項目]

Add new item dialog in Visual Studio.

若要使用範本,請選取所需的範本、指定檔案名稱,然後選取 [新增]。 以這種方式加入項目,會將檔案自動加入您的 Visual Studio 專案,並為原始檔控制標記變更。

問題:Visual Studio 如何知道應提供哪些項目範本?

回答:Visual Studio 專案檔 (.pyproj) 包含將它標示為 Python 專案的專案類型識別碼。 Visual Studio 會使用此類型的識別碼,以便只顯示適用於專案類型的項目範本。 如此一來,Visual Studio 便可為許多專案類型提供豐富的項目範本,而無須要求您每次都要加以排序以整理範本。

步驟 3-2:從您的應用程式提供靜態檔案

在使用 Python (使用任何架構) 建置的 Web 應用程式中,您的 Python 檔案一律在 Web 主機伺服器上執行。 Python 檔案也永遠不會傳輸至使用者的電腦。 不過,其他檔案,例如 CSS 和 JavaScript,僅供瀏覽器使用。 因此,每當主機伺服器要求時,只要依照原樣傳遞它們即可。 這類檔案稱為「靜態」檔案,且 Django 可以自動傳遞這些檔案,而您無需撰寫任何程式碼。

Django 專案預設設定為從應用程式的 static 資料夾提供靜態檔案,這要歸功於 Django 專案之 settings.py 檔案中的這幾行設定:

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.9/howto/static-files/

STATIC_URL = '/static/'

STATIC_ROOT = posixpath.join(*(BASE_DIR.split(os.path.sep) + ['static']))

您可以在 static 中,使用偏好的任何資料夾結構來整理檔案,然後使用該資料夾內的相對路徑來參考檔案。 為了示範此流程,下列步驟會將 CSS 檔案新增至應用程式,然後在 index.html 範本中使用該樣式表:

  1. 在 [方案總管] 中,以滑鼠右鍵按一下 Visual Studio 專案的 HelloDjangoApp 資料夾,選取 [新增]>[新增資料夾],並將資料夾命名為 static

  2. 以滑鼠右鍵按一下 [static] 資料夾,並選取 [新增]>[新增項目]。 在出現的對話方塊中,選取 [Stylesheet] (樣式表) 範本,將檔案命名為 site.css,然後選取 [新增]

    Add new item dialog for static file.

    site.css 檔案會出現在專案中,並在編輯器中開啟。 您的資料夾結構應該如下圖所示:

    Static file structure as shown in Solution Explorer.

  3. site.css 檔案的內容取代為下列程式碼,並儲存檔案:

    .message {
        font-weight: 600;
        color: blue;
    }
    
  4. 將應用程式的 templates/HelloDjangoApp/index.html 檔案取代為下列程式碼。 程式碼會將步驟 2 中使用的 <strong> 元素取代為參考 message 樣式類別的 <span>。 使用樣式類別可讓您在設定元素的樣式時獲得更大彈性。 (若您在使用 VS 2017 15.7 及更舊版本時,尚未將 index.html 檔案移至 templates 中的子資料夾內,請參閱步驟 2-4 中的範本命名空間。)

    <html>
        <head>
            <title>{{ title }}</title>
            {% load static %} <!-- Instruct Django to load static files -->
            <link rel="stylesheet" type="text/css" href="{% static 'site.css' %}" />
        </head>
        <body>
            <span class="message">{{ message }}</span>{{ content }}
        </body>
    </html>
    
  5. 執行專案,以觀察其結果。 當您完成時,請停止伺服器,並判斷是否認可您的變更至原始檔控制 (如 步驟 2 中的說明)。

問:{% load static %} 標籤的用途是什麼?

答:需要有 {% load static %} 這一行,才能在 <head><body> 之類的元素中參考靜態檔案。 本節顯示的範例中,"static files" 是指自訂 Django 範本標籤集,它可讓您使用 {% static %} 語法來參照靜態檔案。 如果沒有 {% load static %},則在應用程式執行時會出現例外狀況。

問題:組織靜態檔案有任何慣例嗎?

答:您可以依偏好將其他的 CSS、JavaScript 和 HTML 檔案新增至您的 static 資料夾。 組織靜態檔案的一般方式是建立名為 fontsscriptscontent 的子資料夾 (針對樣式表和任何其他檔案)。 在各種情況中,請記得要將那些資料夾包含在 {% static %} 參考中的相對檔案路徑。

問:我是否可以在不使用 {% load static %} 標籤的情況下,完成相同的工作?

答:可以。

<html>
    <head>
        <title>{{ title }}</title>
        <link rel="stylesheet" type="text/css" href="../../static/site.css" />
    </head>
    <body>
        <span class="message">{{ message }}</span>{{ content }}
    </body>
</html>

步驟 3-3:將頁面加入應用程式

將其他頁面新增至應用程式將會:

  • 加入定義檢視的 Python 函式。
  • 加入網頁標記的範本。
  • 將必要的路由新增至 Django 專案的 urls.py 檔案。

下列步驟會將 [關於] 頁面新增至 [HelloDjangoApp],並從首頁連結至該頁面:

  1. 在 [方案總管] 中,以滑鼠右鍵按一下 [templates/HelloDjangoApp] 資料夾。 選取 [新增] > [新項目]>,然後選取 [HTML 頁面] 項目範本。 命名檔案 about.html,並選取 [新增]

    Add new item dialog for about file.

    提示

    如果 [新項目] 命令未出現在 [新增] 功能表上,請確認您已停止伺服器,這樣 Visual Studio 就會結束偵錯模式。

  2. about.html 的內容取代為下列標記 (您會在步驟 3-4 中,將首頁的明確連結取代為簡單的導覽列):

    <html>
        <head>
            <title>{{ title }}</title>
            {% load static %}
            <link rel="stylesheet" type="text/css" href="{% static 'site.css' %}" />
        </head>
        <body>
            <div><a href="home">Home</a></div>
            {{ content }}
        </body>
    </html>
    
  3. 開啟應用程式的 views.py 檔案,然後新增使用範本且名為 about 的函式:

    def about(request):
        return render(
            request,
            "HelloDjangoApp/about.html",
            {
                'title' : "About HelloDjangoApp",
                'content' : "Example app page for Django."
            }
        )
    
  4. 開啟 Django 專案的 urls.py 檔案,然後將下列這一行新增至 urlPatterns 陣列:

    re_path(r'^about$', HelloDjangoApp.views.about, name='about'),
    
  5. 開啟 templates/HelloDjangoApp/index.html 檔案,然後將下列這一行新增至 <body> 元素下,以連結到 [關於] 頁面 (同樣地,您會在步驟 3-4 中將此連結取代為導覽列):

    <div><a href="about">About</a></div>
    
  6. 使用 [檔案]>[全部儲存] 功能表命令來儲存所有檔案,或可僅按下 Ctrl+Shift+S。 (技術上來說並不需要此步驟,因為在 Visual Studio 中執行專案會自動儲存檔案。不過,知道有這個命令也很好。)

  7. 執行專案以觀察結果,並檢查頁面之間的瀏覽。 當您完成時,請關閉伺服器。

答:雖然在 views.py 檔案中的檢視函式的 名稱是 index,但是 Django 專案中 urls.py 檔案的 URL 路由模式並不包含符合 "index" (索引) 字串的規則運算式。 若要符合該字串,您必須為 ^index$ 模式新增另一個項目。

如下一節所示,最好是在頁面範本中使用 {% url '<pattern_name>' %} 標籤來參考模式的名稱。 在此情況下,Django 會為您建立適當的 URL。 例如,將 about.html 中的 <div><a href="home">Home</a></div> 取代為 <div><a href="{% url 'index' %}">Home</a></div>。 此處使用 'index' (索引) 得以運作是因為 urls.py 中的第一個 URL 模式事實上是名為 'index' (因為 name='index' 引數之故)。 您也可以使用 'home' (首頁) 來參考第二個模式。

步驟 3-4:使用範本繼承來建立標題和瀏覽列

新式 Web 應用程式會使用商標標頭和導覽列,而不是在每個頁面上有明確的導覽連結。 導覽列提供最重要的頁面連結、快顯功能表等等。 為了確保所有頁面上的標頭和導覽列都相同,您應該不會想在每個頁面範本中重複相同的程式碼。 反之,您應該是在同一個地方定義所有頁面的共同部分。

Django 的範本系統提供兩個方法,可跨多個範本重複使用特定元素:包含和繼承。

  • 「包含」使用 {% include <template_path> %} 語法,在參考範本中的特定位置插入其他頁面範本。 如果您想要以動態方式變更程式碼中的路徑,也可以使用變數。 「包含」用在頁面主體,用來在頁面特定位置引進共用的範本。

  • 「繼承」在頁面範本開頭使用{% extends <template_path> %},以指定共用基底範本,以便參考範本並接著據以建置範本。 「繼承」通常用來定義共用版面配置、瀏覽列和應用程式頁面的其他結構,因此參考範本只能加入或修改名為 blocks (區塊) 的基底範本特定區域。

在這兩種情況下,<template_path> 是相對於應用程式的 templates 資料夾 (也允許 .././)。

基底範本使用 {% block <block_name> %}{% endblock %} 標籤來描述區塊。 若之後參考範本再對同一個區塊名稱使用標籤,其區塊內容將會覆寫基底範本的區塊內容。

下列步驟將示範繼承:

  1. 在應用程式的 templates/HelloDjangoApp 資料夾中,建立新的 HTML 檔案。 以滑鼠右鍵按一下 templates/HelloDjangoApp 資料夾,選取 [新增] > [新項目]>,然後選取 [HTML 頁面] 項目範本。 命名檔案 layout.html,並選取 [新增]

    Add new item dialog for layout file.

  2. layout.html 檔案的內容取代為下列標記。 您可以看到此範本包含一個名為 "content" (內容) 的區塊,這是參考頁面必須全部取代的部分:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <title>{{ title }}</title>
        {% load static %}
        <link rel="stylesheet" type="text/css" href="{% static 'site.css' %}" />
    </head>
    
    <body>
        <div class="navbar">
           <a href="/" class="navbar-brand">Hello Django</a>
           <a href="{% url 'home' %}" class="navbar-item">Home</a>
           <a href="{% url 'about' %}" class="navbar-item">About</a>
        </div>
    
        <div class="body-content">
    {% block content %}{% endblock %}
            <hr/>
            <footer>
                <p>&copy; 2018</p>
            </footer>
        </div>
    </body>
    </html>
    
  3. 將下列樣式新增至應用程式的 static/site.css 檔案 (本逐步解說並非要示範回應式設計;這些樣式只是為了產生有趣的結果):

    .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;
    }
    
  4. 修改 templates/HelloDjangoApp/index.html 檔案,以參考基底範本,並使其在頁面中可用。 將下列這一行新增為 HTML 頁面中的第 1 行 (在 html 標籤上方):

    {% extends "HelloDjangoApp/layout.html" %}
    
  5. 您可以藉由使用繼承看到這一行,此範本會變得很容易在主體標籤內實作,以覆寫內容區塊:

    {% block content %}
    <span class="message">{{ message }}</span>{{ content }}
    {% endblock %}
    
  6. 以相同的方式修改 templates/HelloDjangoApp/about.html 檔案,讓版面配置範本可供使用。 在 HTML 頁面中新增步驟 1 中的相同行 (在 HTML 標籤上方):

    {% extends "HelloDjangoApp/layout.html" %}
    
  7. 然後,使用繼承,在主體標籤內實作範本,以覆寫內容區塊:

    {% block content %}
    {{ content }}
    {% endblock %}
    
  8. 執行伺服器,以觀察其結果。 當您完成時,請關閉伺服器。

    Running app showing the nav bar.

  9. 由於您對應用程式做了大幅變更,因此現在也是認可您的變更至原始檔控制的好時機。

下一步

深入了解