はじめに
DjangoでWebアプリを作るとき、
ユーザーの目に見える部分が テンプレート(Template) です。
- HTMLを書くだけじゃダメなのか
- views.pyとの役割分担がよく分からない
DjangoやWebアプリそのものに慣れていないと
テンプレートの役割や重要性がいまいちわかりにくいですよね。
実際、DjangoのTemplateは単なるHTMLではありません。
データベースから取得した情報や、Viewで処理した内容を
{{ }}
や {% %}
という独自のタグを使って埋め込む仕組み
を持っています。
これにより、動的に変わるWebページを
簡単に作ることが可能です。
例えば、ブログの記事一覧を作りたい場合、
- Viewが「記事データ」を集めてTemplateに渡す
- Templateでは渡された「記事タイトルや本文」
のデータをループで並べて表示する
この役割分担によって、処理とデザインを
きれいに切り分けることができ、
保守性の高いアプリ開発が実現します。
この記事では、私が学習した内容をもとに
Templateの基本的な役割から、
つまずきやすいエラー、実際のコード例などを
まとめていきます。
この記事はこんな方におすすめです!
- DjangoのTemplateが、
ただのHTMLと何が違うのか知りたい方 - Viewとの連携方法があいまいな方
- 自分のWebアプリの画面に、
データを埋め込んで作ってみたい方
第1章:テンプレートの役割
Djangoのテンプレートは、単なるHTMLファイルではありません。
アプリ全体の中では、ユーザーに見せる最終的な画面を担う
重要な役割を果たしています。
ViewやModelと連携することで、
データを見やすく整えて表示する仕組みを持っています。
1. MTVモデルの中での位置づけ
Djangoは、MTVモデルという仕組みに基づいています。
- Model:
データベースとのやりとりを担当 - View:
処理の流れを決める
(データを集めてどのテンプレートを使うか指示) - Template:
ユーザーに見せる画面を生成する
テンプレートは渡されたデータの中身を
そのまま見せるのではなく、
わかりやすく、きれいに表示する役割を持っています。
2. データをHTMLに埋め込む
テンプレートの最大の特徴は、
Djangoテンプレート言語 を使ってデータを埋め込めることです。
簡単な例として、Viewから渡したデータを
テンプレートに表示する場合、
# views.py
def greet_view(request):
context = {"name": "太郎"}
return render(request, "greet.html", context)
<!-- greet.html -->
<p>こんにちは、{{ name }}さん!</p>
ここで {{ }}
といテンプレートタグを使うことで、
データの内容によって、動的に変化するページを
作れるようになります。
また、 {% %}
を使うことで、
HTMLの中で繰り返しや条件分岐を記述できます。
繰り返し:
<ul>
{% for post in posts %}
<li>{{ post.title }}</li>
{% endfor %}
</ul>
条件分岐:
{% if user.is_authenticated %}
<p>{{ user.username }}さん、ようこそ!</p>
{% else %}
<p>ログインしてください。</p>
{% endif %}
これにより、柔軟に表示内容を柔軟に変えることができます。
また、ポートフォリオ作成では、
より業務に近いWebアプリのような画面
を作成することにもつながります。
3. テンプレートの要点
- Djangoにおける画面表示担当であり、
ユーザーにデータを届ける最終工程 - Djangoテンプレート言語を使うことで、
変数埋め込み・繰り返し・条件分岐が可能 - ViewやModelと役割分担し、
処理とデザインを分けることで保守性が高まる - Templateは、アプリ全体を
ユーザーにとって使いやすく整える存在
第2章:つまずきやすいポイント
テンプレートはDjangoの中でも画面を作る部分を担うため、
Webアプリの動作確認時にも触れる機会も多いです。
その分、
- 画面が表示されない
- 変数が出てこない
などのトラブルにもよく直面します。
ここでは私が学習時につまずいたポイントを整理して紹介します。
1. TemplateDoesNotExistエラー
ブラウザで画面にアクセスするとTemplateDoesNotExist
と表示されるエラーです。
主な原因として、
- テンプレートファイルが正しい場所にない
templates/
フォルダの構成が間違っているsettings.py
のTEMPLATES['DIRS']
にパスを設定していない
これを解消するために、見直したいポイントは
- アプリごとに
templates/アプリ名/ファイル.html
の構成にする render()
で呼ぶときは、
アプリ名を含めたパスを書くreturn render(request, "users/signup.html")
テンプレートファイルの配置場所と、
Viewからのパス指定が合っているか
をまず確認することが基本ですが重要です。
2. 変数が表示されない
Viewからデータを渡しているのに、画面表示時に出てこない。
これもよくある不具合です。
単純ではありますが、誤りの例として、
# views.py
def greet_view(request):
context = {"username": "太郎"}
return render(request, "greet.html", context)
<!-- greet.html -->
<p>こんにちは、{{ name }}さん!</p>
ここでは、Viewで渡しているキーは username
なのに、
テンプレート側で name
を呼び出しているため、
何も表示されません。
解消するために確認したいポイントとして、
- View側のキー名とテンプレート側の変数名を
一致させる - デバッグ時で、
変数の値を設定していない場合などは{{ 変数|default:"値なし" }}
と書くと確認しやすい
3. 静的ファイル(CSSや画像)が反映されない
テンプレートで見た目を整えようとしたときに、
HTMLと同様にCSSなど静的ファイルの読み込みが可能です。
そのCSSや画像が表示されないトラブルもよくあります。
主な原因としては、
{% load static %}
を書き忘れている- ファイルを
static/
フォルダに置いていない - 本番環境で
collectstatic
をしていない
静的ファイルのテンプレートでの読み込みの
正しい書き方は以下です。
{% load static %}
<link rel="stylesheet" href="{% static 'css/style.css' %}">
<img src="{% static 'images/logo.png' %}" alt="ロゴ">
Djangoでは、静的ファイルを扱うために static/
フォルダ を準備しておき、
その配下に、CSSなどのファイルを配置することで
Djangoが対象の静的ファイルを認識できるようになります。
詳しくは次の章でまとめます。
4. forループやif文が効かない
テンプレートの構文はシンプルですが、
よくミスするのが タグの閉じ忘れ です。
これは、テンプレートに限った話ではないですが
HTML同様に開始、終了のタグはペアになるように
注意しましょう。
HTMLタグは一部、終了タグの記載漏れでも
ブラウザ側で補完され、挙動に問題なく見える場合もあります。
しかし、Djangoのテンプレート言語でのタグを利用する場合は
必ず、このセットに漏れがないようにしましょう。
誤り例としては、
{% for post in posts %}
<p>{{ post.title }}</p>
<!-- {% endfor %} がない -->
上記のような誤りの場合、正しい書き方として、
{% for post in posts %}
<p>{{ post.title }}</p>
{% endfor %}
5. ハードコーディングでのリンク切れ
テンプレートとurls.py
の関係を曖昧なまま
Webアプリを作成していると、
画面遷移のためのリンクを作るときに、
次のように書いてしまいがちです。
<a href="/signup/">登録</a>
一見問題なく見えます。
また、実際にこのURLがurls.py
で
マッピングされていれば問題ありません。
しかし、マッピングのためのURLを後から変更すると
リンクがすべて壊れてしまいます。
これらの問題を発生しないようにするためにも、
URLのハードコードは行わず、
必ず urls.py
の name
を使って参照するようにしましょう。
<a href="{% url 'users:signup' %}">登録</a>
第3章:実際のテンプレートの定義
テンプレートは、ユーザーに見せる最終的な画面を作る場所です。
押さえるべきテンプレートの定義の要点をまとめます。
これらは基本となりますが、
Webアプリの開発では非常に利用する内容です。
1. 変数の埋め込み
Viewから渡したデータは、
テンプレートで {{ }}
を使って表示できます。
Viewとテンプレートの変数名が一致していることが重要です。
# views.py
def greet_view(request):
context = {"name": "太郎"}
return render(request, "greet.html", context)
<!-- greet.html -->
<p>こんにちは、{{ name }}さん!</p>
2. 繰り返し処理
複数のデータを一覧表示したい場合、{% for %}
を使います。
forループは一覧ページや、
複数要素をまとめて表示する時の基本パターンです。
# views.py
def post_list(request):
posts = [
{"title": "記事1", "author": "山田"},
{"title": "記事2", "author": "佐藤"},
]
return render(request, "post_list.html", {"posts": posts})
<!-- post_list.html -->
<ul>
{% for post in posts %}
<li>{{ post.title }}({{ post.author }})</li>
{% endfor %}
</ul>
3. 条件分岐
テンプレートでは {% if %}
を使って、
条件によって表示を変えることができます。
{% if user.is_authenticated %}
<p>{{ user.username }}さん、ようこそ!</p>
{% else %}
<p>ログインしてください。</p>
{% endif %}
例えば、Viewからの渡されたデータで、
値がある場合のみ画面に表示するなどの制御に便利です。
また、指定の要素を判定して、対象のCSSのスタイルを当てるなど
画面の表示での様々な条件分けにも応用できます。
4. テンプレートの継承
大規模なアプリでは、画面数も相当数になるので
共通部分(ヘッダーやフッターなど)を毎回書くのは非効率です。
そこで使うのが テンプレート継承 です。
Webアプリなどでは、サイトのヘッダー部分は
常に共通として見栄えを統一することも多いため
ベースとなるテンプレートを準備し、各画面に引き継がせることで
それぞれの画面で統一感のある見た目に整えることが可能です。
ベーステンプレート(base.html)の例として、
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>{% block title %}My Site{% endblock %}</title>
{% load static %}
<link rel="stylesheet" href="{% static 'css/style.css' %}">
</head>
<body>
<header>
<h1>共通ヘッダー</h1>
</header>
<main>
{% block content %}{% endblock %}
</main>
<footer>
<p>フッター</p>
</footer>
</body>
</html>
そして、各画面となるテンプレートでは、
ベーステンプレートの{% block content %}
の部分のみ
を作成するのが基本となります。
{% extends "base.html" %}
{% block title %}トップページ{% endblock %}
{% block content %}
<h2>記事一覧</h2>
<p>ここに記事を表示します。</p>
{% endblock %}
5. 静的ファイルの利用
画面デザインを整えるために、
CSSや画像などの静的ファイルを読み込みます。
その際の、Webアプリのフォルダ構成として、static
フォルダを準備し、
その配下に静的ファイルを配置するようにします。
project_root/
└── static/
├── css/
│ └── style.css
└── images/
└── logo.png
テンプレートで、読み込む際には
{% load static %}
<link rel="stylesheet" href="{% static 'css/style.css' %}">
<img src="{% static 'images/logo.png' %}" alt="ロゴ">
{% load static %}
を忘れると
Djangoが静的ファイルを配置しているフォルダを見つけられず
読み込めないので、必ずテンプレートの先頭に書きましょう。
6. URLの逆引き
リンクを作るときは、ハードコーディングせずに
{% url %}
を使います。
URLが変更されても、urls.py
のnameが
一致していればリンクは壊れません。
<a href="{% url 'users:signup' %}">ユーザー登録</a>
<a href="{% url 'blog:post_list' %}">記事一覧</a>
7. フィルターでデータを整形
Djangoのテンプレートでは
フィルター を使って表示内容を加工できます。
<p>投稿日: {{ post.created_at|date:"Y年m月d日" }}</p>
<p>本文: {{ post.content|truncatechars:20 }}</p>
date:"Y年m月d日"
→ 日付を整形truncatechars:20
→ 文字数を20文字に制限
見た目を調整するときに、バックエンド側で加工せずに
テンプレート側で適用できるため便利な機能です。
第4章:まとめ
ここまで、Djangoの テンプレートについて
私が学習した内容をもとに基本を中心にまとめていきました。
要点としては、
- Templateが、ユーザーに見せる画面を担う役割
- データを変数として埋め込み動的な画面にできる
- 繰り返し、条件分岐、継承等で
柔軟に画面を定義できる
テンプレートは、ただのHTMLではありません。
ViewやModelと役割を分けて設計することで、
保守性が高く、使いやすいWebアプリを作ることができます。
テンプレートを押さえると、
見た目を動かす楽しさを実感しやすいです。
また、バックエンド側で加工したデータなどの
整理のしやすさも利点としてあります。
私も現在、Djangoで
ポートフォリオ用のWebアプリを作成しています。
また、なにか気づきがあれば記事にしていこうと思います。