步驟 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 都提供方便您著手的項目範本。
若要檢視可用的範本,請移至 [方案總管],以滑鼠右鍵按一下您要建立項目的資料夾,然後選取 [新增]>[新項目]。
若要使用範本,請選取所需的範本、指定檔案名稱,然後選取 [新增]。 以這種方式加入項目,會將檔案自動加入您的 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 範本中使用該樣式表:
在 [方案總管] 中,以滑鼠右鍵按一下 Visual Studio 專案的 HelloDjangoApp 資料夾,選取 [新增]>[新增資料夾],並將資料夾命名為
static
。以滑鼠右鍵按一下 [static] 資料夾,並選取 [新增]>[新增項目]。 在出現的對話方塊中,選取 [Stylesheet] (樣式表) 範本,將檔案命名為
site.css
,然後選取 [新增]。site.css 檔案會出現在專案中,並在編輯器中開啟。 您的資料夾結構應該如下圖所示:
將 site.css 檔案的內容取代為下列程式碼,並儲存檔案:
.message { font-weight: 600; color: blue; }
將應用程式的 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>
執行專案,以觀察其結果。 當您完成時,請停止伺服器,並判斷是否認可您的變更至原始檔控制 (如 步驟 2 中的說明)。
問:{% load static %} 標籤的用途是什麼?
答:需要有 {% load static %}
這一行,才能在 <head>
和 <body>
之類的元素中參考靜態檔案。 本節顯示的範例中,"static files" 是指自訂 Django 範本標籤集,它可讓您使用 {% static %}
語法來參照靜態檔案。 如果沒有 {% load static %}
,則在應用程式執行時會出現例外狀況。
問題:組織靜態檔案有任何慣例嗎?
答:您可以依偏好將其他的 CSS、JavaScript 和 HTML 檔案新增至您的 static 資料夾。 組織靜態檔案的一般方式是建立名為 fonts、scripts 和 content 的子資料夾 (針對樣式表和任何其他檔案)。 在各種情況中,請記得要將那些資料夾包含在 {% 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],並從首頁連結至該頁面:
在 [方案總管] 中,以滑鼠右鍵按一下 [templates/HelloDjangoApp] 資料夾。 選取 [新增] > [新項目]>,然後選取 [HTML 頁面] 項目範本。 命名檔案
about.html
,並選取 [新增]。提示
如果 [新項目] 命令未出現在 [新增] 功能表上,請確認您已停止伺服器,這樣 Visual Studio 就會結束偵錯模式。
將 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>
開啟應用程式的 views.py 檔案,然後新增使用範本且名為
about
的函式:def about(request): return render( request, "HelloDjangoApp/about.html", { 'title' : "About HelloDjangoApp", 'content' : "Example app page for Django." } )
開啟 Django 專案的 urls.py 檔案,然後將下列這一行新增至
urlPatterns
陣列:re_path(r'^about$', HelloDjangoApp.views.about, name='about'),
開啟 templates/HelloDjangoApp/index.html 檔案,然後將下列這一行新增至
<body>
元素下,以連結到 [關於] 頁面 (同樣地,您會在步驟 3-4 中將此連結取代為導覽列):<div><a href="about">About</a></div>
使用 [檔案]>[全部儲存] 功能表命令來儲存所有檔案,或可僅按下 Ctrl+Shift+S。 (技術上來說並不需要此步驟,因為在 Visual Studio 中執行專案會自動儲存檔案。不過,知道有這個命令也很好。)
執行專案以觀察結果,並檢查頁面之間的瀏覽。 當您完成時,請關閉伺服器。
問題:我嘗試使用 "index" (索引) 於首頁連結,但無法運作。 為何會這樣?
答:雖然在 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 %}
標籤來描述區塊。 若之後參考範本再對同一個區塊名稱使用標籤,其區塊內容將會覆寫基底範本的區塊內容。
下列步驟將示範繼承:
在應用程式的 templates/HelloDjangoApp 資料夾中,建立新的 HTML 檔案。 以滑鼠右鍵按一下 templates/HelloDjangoApp 資料夾,選取 [新增] > [新項目]>,然後選取 [HTML 頁面] 項目範本。 命名檔案
layout.html
,並選取 [新增]。將 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>© 2018</p> </footer> </div> </body> </html>
將下列樣式新增至應用程式的 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; }
修改 templates/HelloDjangoApp/index.html 檔案,以參考基底範本,並使其在頁面中可用。 將下列這一行新增為 HTML 頁面中的第 1 行 (在 html 標籤上方):
{% extends "HelloDjangoApp/layout.html" %}
您可以藉由使用繼承看到這一行,此範本會變得很容易在主體標籤內實作,以覆寫內容區塊:
{% block content %} <span class="message">{{ message }}</span>{{ content }} {% endblock %}
以相同的方式修改 templates/HelloDjangoApp/about.html 檔案,讓版面配置範本可供使用。 在 HTML 頁面中新增步驟 1 中的相同行 (在 HTML 標籤上方):
{% extends "HelloDjangoApp/layout.html" %}
然後,使用繼承,在主體標籤內實作範本,以覆寫內容區塊:
{% block content %} {{ content }} {% endblock %}
執行伺服器,以觀察其結果。 當您完成時,請關閉伺服器。
由於您對應用程式做了大幅變更,因此現在也是認可您的變更至原始檔控制的好時機。
下一步
深入了解
- 撰寫您的第一個 Django 應用程式,第 3 部分 (檢視) \(英文\) (docs.djangoproject.com)
- 如需了解更多 Django 範本的功能,例如控制流程,請參閱 Django 範本語言 \(英文\) (docs.djangoproject.com)
- 如需使用
{% url %}
標籤的完整詳細資料,請參閱 Django 範本的內建範本標籤和篩選參考 \(英文\) (docs.djangoproject.com) 中的 url \(英文\) - GitHub 上的教學課程原始程式碼:Microsoft/python-sample-vs-learning-django