跳轉到

第一個 Template

開始之前

任務目標

在這個章節中,我們會完成:

  • 了解 HTML 基礎概念
  • 了解 Django Template 的用途
  • 建立 templates 資料夾結構
  • 將 View 改為使用 Template 渲染

什麼是 HTML?

HTML(HyperText Markup Language)是網頁的骨架,用來定義網頁的結構和內容。

HTML 基本結構

<!DOCTYPE html>
<html>
<head>
    <title>頁面標題</title>
</head>
<body>
    <h1>這是標題</h1>
    <p>這是段落</p>
</body>
</html>

常用標籤

標籤 說明 範例
<h1> ~ <h6> 標題(h1 最大,h6 最小) <h1>大標題</h1>
<p> 段落 <p>這是一段文字</p>
<a> 連結 <a href="url">連結文字</a>
<div> 區塊容器 <div>內容</div>
<span> 行內容器 <span>文字</span>

學習 HTML

HTML 內容非常豐富,這裡只是簡單介紹。建議參考 MDN Web Docs 學習更多。

透過 Django 回應 HTML

讓我們修改剛剛建立的 view 讓他回應 HTML 的內容

practices/views.py
from django.http import HttpResponse


def hello_world(request):
    return HttpResponse("<h1>Hello, World!</h1>")

接著我們打開網頁 http://127.0.0.1:8000/practices/hello/,應該會發現回應的 Hello, World! 字變大了,因為我們用 <h1> 標籤將它包起來了

什麼是 Django Template?

在前面的章節中,我們直接在 View 中回傳 HTML 字串:

def hello_world(request):
    return HttpResponse("<h1>Hello, World!</h1>")

這種方式對於簡單的回應沒問題,但當需要回傳完整的 HTML 頁面時,把 HTML 寫在 Python 程式碼中會變得難以維護。

Template(模板) 讓我們把 HTML 和 Python 邏輯分開:

  • View 負責處理邏輯和準備資料
  • Template 負責呈現頁面

建立 Template

步驟 1:建立 templates 資料夾

practices App 中建立 templates 資料夾,並在裡面再建立一個 practices 資料夾:

mkdir -p practices/templates/practices

目錄結構如下:

practices/
├── templates/
│   └── practices/      # 與 App 同名的資料夾
│       └── (templates 放這裡)
├── views.py
└── ...

為什麼要多一層資料夾?

Django 會在所有 App 的 templates 資料夾中搜尋模板。如果多個 App 有相同名稱的模板,可能會造成衝突。

加上 App 名稱的資料夾可以避免這個問題。

步驟 2:建立 Template 檔案

建立 practices/templates/practices/hello.html

practices/templates/practices/hello.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="This is my first Django Template" />
    <meta name="keywords" content="Django, Template, HTML" />
    <title>Hello</title>
  </head>
  <body>
    <h1>
      Hello, World!
    </h1>
    <p>
      這是我的第一個 Django Template
    </p>
  </body>
</html>

步驟 3:修改 View 使用 Template

修改 practices/views.py,使用 render() 函式來渲染 Template:

practices/views.py
from django.shortcuts import render


def hello_world(request):
    return render(request, "practices/hello.html")

render() 函式:

  • 第一個參數:request 物件
  • 第二個參數:Template 的路徑(相對於 templates 資料夾)

步驟 4:測試

啟動開發伺服器並訪問 http://127.0.0.1:8000/practices/hello/,你應該會看到完整的 HTML 頁面。

Template 的排版

我們前面在設定 VSCode 時已經安裝了 djlint 這個套件,但是那只是安裝了讓 VSCode 可以操作這個排版工具的套件而已,我們需要自己安裝工具本身

uv add --group=check djlint

透過上面的指令我們安裝了 djlint 這個排版工具,這樣就可以順利自動排版 Template 檔案了

套件分組

這個指令出現了 --group=check 這個參數,代表的是我要將 djlint 這個套件安裝到 check 這個分類中,因為 djlint 不是網站執行所需要的套件他只是我們開發的協助工具,好好分類能讓我們知道套件被用在哪個情境,同時讓我們能夠在部署時只安裝最少的套件以節省資源

接著我們在 pyproject.toml 中加入以下設定

pyproject.toml
# ... 以上省略 ...

[tool.djlint]
profile = "django"
max_blank_lines = 1
line_break_after_multiline_tag = true
uv group 的使用

設定預設群組,當你有多個群組時,可以在 pyproject.toml 中設定哪些群組預設要安裝:

pyproject.toml
# ... 以上省略 ...

[tool.uv]
default-groups = ["check"]

# ... 以下省略 ...

這樣執行 uv sync 時,就會自動安裝 check 群組的套件。


排除特定群組,在部署到正式環境時,你可能不需要開發工具。可以使用 --no-group 排除特定群組:

# 排除 check 群組
uv sync --no-group check

# 排除多個群組
uv sync --no-group dev --no-group check

只安裝特定群組,如果只想安裝特定群組,可以使用 --only-group

# 只安裝 check 群組(用於 CI 檢查)
uv sync --only-group check

只安裝特定群組與主要依賴,如果只想安裝特定群組,可以使用 --group

# 只安裝 check 群組與主要依賴
uv sync --group check

傳遞資料到 Template

Template 的強大之處在於可以動態顯示資料。

步驟 1:建立帶有變數的 Template

建立 practices/templates/practices/greeting.html

practices/templates/practices/greeting.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="This is my first Django Template" />
    <meta name="keywords" content="Django, Template, HTML" />
    <title>Greeting</title>
  </head>
  <body>
    <h1>
      Hello, {{ name }}!
    </h1>
    <p>
      歡迎來到 Django 的世界
    </p>
  </body>
</html>

{{ name }} 是 Django Template 的變數語法,會被替換成實際的值。

步驟 2:修改 View 傳遞資料

practices/views.py 中新增一個 View:

practices/views.py
from django.shortcuts import render


def hello_world(request):
    return render(request, "practices/hello.html")


def greeting(request):
    name = "Django"
    return render(request, "practices/greeting.html", {"name": name})

render() 的第三個參數是一個字典,稱為 context,包含要傳遞給 Template 的資料。

步驟 3:設定 URL

practices/urls.py 中新增路由:

practices/urls.py
from django.urls import path

from practices import views

urlpatterns = [
    path("hello/", views.hello_world, name="hello_world"),
    path("greeting/", views.greeting, name="greeting"),
]

步驟 4:測試

訪問 http://127.0.0.1:8000/practices/greeting/,你應該會看到 "Hello, Django!"。

Template 語法簡介

Django Template 有幾種基本語法:

語法 說明 範例
{{ variable }} 顯示變數 {{ name }}
{% tag %} 模板標籤(邏輯控制) {% if %}, {% for %}
{# comment #} 註解 {# 這是註解 #}

變數範例

<p>姓名:{{ user.name }}</p>
<p>年齡:{{ user.age }}</p>

條件判斷範例

{% if user.is_authenticated %}
    <p>歡迎回來,{{ user.name }}!</p>
{% else %}
    <p>請先登入</p>
{% endif %}

迴圈範例

<ul>
    {% for item in items %}
        <li>{{ item }}</li>
    {% endfor %}
</ul>

更多 Template 語法

Django Template 還有很多功能,如 filter、繼承等。我們會在後面的章節中詳細介紹。

重點整理

概念 說明
Template 用來呈現 HTML 頁面的檔案
render() 渲染 Template 並回傳 HttpResponse
Context 傳遞給 Template 的資料字典
{{ }} 顯示變數的語法
{% %} 模板標籤的語法

任務結束

完成!

恭喜你完成了這個章節!現在你已經:

  • 了解 HTML 基礎概念
  • 了解 Django Template 的用途
  • 建立 templates 資料夾結構
  • 將 View 改為使用 Template 渲染