概要(Django のテンプレート=「HTML にデータを流し込む仕組み」)
Django のテンプレートは、
「HTML のひな型(型)をあらかじめ用意しておいて、
ビューから渡されたデータをそこに流し込んで、完成した HTML を作る仕組み」
です。
Python のコードの中に HTML をベタ書きすると、
すぐにぐちゃぐちゃになります。
テンプレートを使うと、
見た目(HTML・レイアウト)はテンプレートファイルにまとめる
中身のデータ(ユーザー名、一覧、メッセージなど)はビューから渡す
という役割分担ができて、コードが一気に整理されます。
Django のテンプレートエンジンは Jinja2 に似た独自方言ですが、
考え方はほぼ同じで、
{{ ... }} で値を埋め込む{% ... %} で if や for などの制御を書く
というルールさえ押さえれば、すぐに使いこなせます。
「Python の中に HTML を書く」世界がなぜつらいか
文字列で HTML を返すだけだとすぐ限界が来る
まず、テンプレートを使わない場合をイメージしてみます。
ビューの中で直接 HTML を返すコードはこうなります。
from django.http import HttpResponse
def hello(request):
username = "Taro"
html = f"""
<html>
<head><title>Hello</title></head>
<body>
<h1>こんにちは、{username} さん</h1>
</body>
</html>
"""
return HttpResponse(html)
Python最初は「これで十分じゃん」と感じます。
でも、少しずつ機能が増えると一気に破綻します。
複数ページで同じヘッダやフッタを使い回したくなる
ログイン状態によって表示を変えたくなる
一覧表示や条件分岐が増えて HTML がどんどん長くなる
そのたびに Python のファイルの中で
巨大な文字列を編集することになり、
見た目の修正とロジックの修正がごちゃ混ぜになります。
ここで「見た目は HTML ファイルに分離しよう」という発想が出てきます。
それを支えるのが Django のテンプレートです。
Django テンプレートの基本イメージ
「HTML の中に、あとで埋める“穴”を開けておく」
テンプレートでは、まず普通の HTML ファイルを作ります。
そこに「あとでビューから渡す値」を埋め込む場所を、{{ 変数名 }} という形で書いておきます。
例えば、templates/hello.html を作ります。
<!DOCTYPE html>
<html>
<head>
<title>Hello</title>
</head>
<body>
<h1>こんにちは、{{ username }} さん</h1>
</body>
</html>
この {{ username }} が「穴」です。
ビューから username という名前で値を渡すと、
ここにその値が差し込まれます。
Django のテンプレートエンジンは、
{{ ... }} を「値を表示する場所」{% ... %} を「制御構文を書く場所」
として解釈します。
ビュー側では、このテンプレートを「レンダリング」して返します。
ビューからテンプレートを使う基本パターン
render() を使ってテンプレート+コンテキストを返す
Django では、テンプレートを使ったビューはだいたいこう書きます。
from django.shortcuts import render
def hello(request):
context = {"username": "Taro"}
return render(request, "hello.html", context)
Pythonここで重要なポイントを整理します。
一つ目。render() は「テンプレートを読み込んで、コンテキスト(データ)を流し込み、HttpResponse を返す」便利関数です。
テンプレート名(”hello.html”)と、テンプレートに渡したい値の辞書(context)を渡します。
二つ目。テンプレートファイルは通常、アプリの templates ディレクトリに置きます。
例えば myapp/templates/hello.html のような構成です。settings.py の TEMPLATES 設定で、どのディレクトリをテンプレート検索パスにするかを指定します。
三つ目。テンプレートに渡したい値は、{"キー": 値} の形で辞書に入れます。
テンプレート側では、そのキー名で参照できます。
この例では、context = {"username": "Taro"} としているので、
テンプレート内の {{ username }} が "Taro" に置き換わります。
テンプレートの基本文法(変数・for・if)
変数展開:{{ 変数名 }} で値を表示する
テンプレートの一番基本は「変数を表示する」ことです。
ビュー側でこう渡したとします。
def profile(request):
user = {"name": "Taro", "age": 20}
return render(request, "profile.html", {"user": user})
Pythonテンプレート profile.html ではこう書けます。
<p>名前: {{ user.name }}</p>
<p>年齢: {{ user.age }}</p>
{{ user.name }} のように、ドットで属性やキーにアクセスできます。
辞書でもオブジェクトでも、同じように扱えます。
繰り返し:{% for … %} ~ {% endfor %}
一覧表示をするときは、for 文を使います。
ビュー側:
def item_list(request):
items = [
{"name": "Apple", "price": 100},
{"name": "Banana", "price": 80},
]
return render(request, "items.html", {"items": items})
Pythonテンプレート items.html:
<h1>商品一覧</h1>
<ul>
{% for item in items %}
<li>{{ item.name }}: {{ item.price }} 円</li>
{% endfor %}
</ul>
ここでのポイントは、
{% for item in items %} でループ開始{% endfor %} でループ終了
中では {{ item.name }} のように変数展開
という構造です。
Python の for 文に似ていますが、
テンプレートでは {% %} で囲むことを忘れないでください。
条件分岐:{% if … %} ~ {% endif %}
表示内容を条件によって変えたいときは if を使います。
ビュー側:
def home(request):
user = {"name": "Taro"} # ログインしていないときは None にするなど
return render(request, "home.html", {"user": user})
Pythonテンプレート home.html:
<body>
{% if user %}
<p>こんにちは、{{ user.name }} さん</p>
{% else %}
<p>こんにちは、ゲストさん</p>
{% endif %}
</body>
{% if 条件 %}{% else %}{% endif %}
という形で、かなり Python に近い感覚で書けます。
この「ちょっとした条件分岐」をテンプレート側に寄せることで、
ビューのコードをスリムに保てます。
テンプレート継承(共通レイアウトを一箇所にまとめる)
base.html で「サイト全体の骨組み」を定義する
テンプレートの強力な機能が「継承」です。
全ページ共通のヘッダやフッタ、レイアウトを base.html にまとめておき、
各ページは「中身だけ」差し替える、という構造にできます。
templates/base.html:
<!DOCTYPE html>
<html>
<head>
<title>{% block title %}My Site{% endblock %}</title>
</head>
<body>
<header>
<h1>My Site</h1>
</header>
<main>
{% block content %}{% endblock %}
</main>
<footer>
<p>© 2025 My Site</p>
</footer>
</body>
</html>
ここで {% block title %} や {% block content %} が
「子テンプレートが中身を差し込む場所」です。
各ページのテンプレートで base.html を継承する
トップページ用のテンプレートを作ります。
templates/index.html:
{% extends "base.html" %}
{% block title %}ホーム{% endblock %}
{% block content %}
<p>ようこそ、トップページへ。</p>
{% endblock %}
{% extends "base.html" %} で「このテンプレートは base.html を土台にする」と宣言し、{% block ... %}{% endblock %} で base.html のブロックを上書きします。
結果として、
HTML の骨組み(head, header, footer)は base.html
ページごとの中身(main の中身や title)は index.html
という構造になります。
これにより、
ヘッダやメニューを一箇所で管理できる
ページ追加時は「中身だけ書けばいい」
という、とても保守しやすい状態になります。
テンプレートとビューの役割分担(ここが一番大事)
ビューは「データを集めてテンプレートに渡す人」
Django の設計思想では、
モデル:データの構造と DB 操作
ビュー:リクエストを受けて、必要なデータを集め、どのテンプレートを使うか決める
テンプレート:見た目(HTML)と簡単な表示ロジック
という役割分担になっています。
例えば「本の一覧ページ」を作るとき、
ビューはこうなります。
from django.shortcuts import render
from .models import Book
def book_list(request):
books = Book.objects.all()
return render(request, "book_list.html", {"books": books})
Pythonテンプレート book_list.html はこうです。
<h1>本の一覧</h1>
<ul>
{% for book in books %}
<li>{{ book.title }}</li>
{% endfor %}
</ul>
ここでの分担は、
ビュー:Book.objects.all() でデータを集める
テンプレート:渡された books をどう表示するかだけ考える
という形です。
テンプレートに「やらせすぎない」ことが大事
テンプレートは便利なので、
頑張ればかなり複雑なロジックも書けてしまいます。
でも、初心者のうちは特に、
テンプレートには「表示に必要な最低限のロジック」だけ
重い計算や複雑な条件分岐はビュー側で済ませておく
という意識を持つと、
コードがぐっと読みやすくなります。
例えば、「価格を 3 桁区切りで表示したい」なら、
ビュー側で "{:,}".format(price) してからテンプレートに渡す、
というのも立派な選択肢です。
慣れてきたら、テンプレートフィルタやカスタムタグで
表示用のロジックをテンプレート側に寄せる、というステップに進めば十分です。
まとめ(Django テンプレートは「HTML と Python をきれいに分けるための土台」)
Django のテンプレートを初心者向けに整理すると、こうなります。
テンプレートは「HTML のひな型」に {{ 変数 }} や {% if %} {% for %} を書いておき、ビューから渡されたデータを流し込んで最終的な HTML を作る仕組み。
ビューでは render(request, "template.html", context) と書くだけで、テンプレートにデータを渡して HttpResponse を返せる。テンプレート側では context のキー名で値を参照できる。{{ ... }} で値を表示し、{% for ... %}{% endfor %} や {% if ... %}{% endif %} で一覧表示や条件分岐を表現する。これは「見た目寄りのロジック」としてテンプレートに任せる。base.html を作って {% extends %} と {% block %} を使うと、ヘッダ・フッタなどの共通レイアウトとページごとの中身をきれいに分離できる。
設計の肝は、「データ取得やビジネスロジックはビュー(+モデル)、表示とレイアウトはテンプレート」という役割分担を意識すること。これができると、Django のコードが一気に整理されていく。
