この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:8
ページ更新者:T
更新日時:2026-06-11 07:29:05

タイトル: テンプレート(Template)
SEOタイトル: Django テンプレート完全ガイド — 構文 / 継承 / カスタムタグ

この本文には実行可能なタグ等が含まれるため、安全のためHTMLソースとして表示しています。本文データは変更していません。

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;background:#fffbea;border:1px solid #f4c430;margin:1em 0;width:100%"><tr><td style="background:#f4c430;color:#000;font-weight:bold;padding:8px">この記事の要点</td></tr><tr><td style="padding:10px"><ul><li>Django テンプレートは HTML の中に <strong>変数 <code>{{ var }}</code></strong>・<strong>タグ <code>{% ... %}</code></strong>・<strong>フィルタ <code>{{ var|filter }}</code></strong> を埋め込むテンプレート言語</li><li>ファイルは <code>app/templates/app/index.html</code> に配置。<code>render(request, &quot;app/index.html&quot;, context)</code> で呼ぶ</li><li>継承: <code>{% extends &quot;base.html&quot; %}</code> + <code>{% block content %}{% endblock %}</code> で共通レイアウト</li><li>制御: <code>{% if %}</code> / <code>{% for %}</code> / <code>{% url &quot;name&quot; %}</code> / <code>{% include &quot;_partial.html&quot; %}</code> / <code>{% static &quot;path&quot; %}</code></li><li>カスタムタグ/フィルタは <code>templatetags/</code> 配下に作成し <code>{% load %}</code> で読み込む</li></ul></td></tr></table>
<h2>Django テンプレートとは</h2>

<p>Django テンプレートは、HTML と <strong>テンプレート構文</strong>を混在させて、動的な HTML を組み立てる仕組みです。プログラマでなくてもデザイナが触れるよう、Python の構文ではなく独自の DSL を採用しています。</p>

<h2>配置と呼び出し</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-text">myapp/
├── views.py
├── models.py
└── templates/
    └── myapp/
        ├── base.html
        ├── index.html
        └── detail.html</code></pre><pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-python"># myapp/views.py
from django.shortcuts import render

def index(request):
    context = {
        &quot;title&quot;: &quot;記事一覧&quot;,
        &quot;articles&quot;: Article.objects.all(),
        &quot;user_name&quot;: &quot;taro&quot;,
    }
    return render(request, &quot;myapp/index.html&quot;, context)</code></pre>
<h2>変数・フィルタ・タグの 3 構文</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-django">{# 1. 変数 #}
&lt;h1&gt;{{ title }}&lt;/h1&gt;
&lt;p&gt;こんにちは、{{ user_name }} さん&lt;/p&gt;

{# 2. フィルタ #}
&lt;p&gt;{{ name|upper }}&lt;/p&gt;                    {# 大文字 #}
&lt;p&gt;{{ body|truncatechars:50 }}&lt;/p&gt;          {# 50 文字で切る #}
&lt;p&gt;{{ price|floatformat:2 }}&lt;/p&gt;            {# 小数 2 桁 #}
&lt;p&gt;{{ created_at|date:&quot;Y-m-d H:i&quot; }}&lt;/p&gt;   {# 日付フォーマット #}
&lt;p&gt;{{ html|safe }}&lt;/p&gt;                      {# エスケープ無効 (安全な場合のみ) #}
&lt;p&gt;{{ var|default:&quot;未設定&quot; }}&lt;/p&gt;           {# null/空のときの代替値 #}

{# 3. タグ #}
{% if articles %}
  &lt;ul&gt;
    {% for a in articles %}
      &lt;li&gt;{{ a.title }}&lt;/li&gt;
    {% endfor %}
  &lt;/ul&gt;
{% else %}
  &lt;p&gt;記事はありません&lt;/p&gt;
{% endif %}</code></pre>
<h2>主要フィルタ一覧</h2>

<table border="1" cellpadding="6" cellspacing="0" style="border-collapse:collapse;width:100%">
<thead><tr style="background:#e3f2fd"><th>フィルタ</th><th>用途</th><th>例</th></tr></thead>
<tbody>
<tr><td><code>upper</code> / <code>lower</code></td><td>大文字/小文字</td><td><code>{{ s|upper }}</code></td></tr>
<tr><td><code>title</code></td><td>各単語の頭文字を大文字</td><td><code>{{ s|title }}</code></td></tr>
<tr><td><code>length</code></td><td>長さ</td><td><code>{{ list|length }}</code></td></tr>
<tr><td><code>truncatechars:N</code></td><td>N 文字で切る</td><td><code>{{ s|truncatechars:50 }}</code></td></tr>
<tr><td><code>date:&quot;Y-m-d&quot;</code></td><td>日付フォーマット</td><td><code>{{ dt|date:&quot;Y-m-d&quot; }}</code></td></tr>
<tr><td><code>floatformat:N</code></td><td>小数点 N 桁</td><td><code>{{ p|floatformat:2 }}</code></td></tr>
<tr><td><code>default:&quot;-&quot;</code></td><td>null/空時の代替</td><td><code>{{ v|default:&quot;-&quot; }}</code></td></tr>
<tr><td><code>safe</code></td><td>HTML エスケープを無効化</td><td><code>{{ html|safe }}</code></td></tr>
<tr><td><code>escape</code></td><td>HTML エスケープ</td><td><code>{{ s|escape }}</code></td></tr>
<tr><td><code>linebreaks</code></td><td>改行を <br> / <p> に</td><td><code>{{ s|linebreaks }}</code></td></tr>
<tr><td><code>add:N</code></td><td>加算</td><td><code>{{ n|add:1 }}</code></td></tr>
<tr><td><code>join:&quot;,&quot;</code></td><td>配列を結合</td><td><code>{{ list|join:&quot;,&quot; }}</code></td></tr>
</tbody>
</table>

<h2>主要タグ一覧</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-django">{# for ループ #}
{% for a in articles %}
  {{ forloop.counter }}: {{ a.title }}
{% empty %}
  記事なし
{% endfor %}

{# if #}
{% if user.is_authenticated %}
  ようこそ {{ user.username }} さん
{% elif user.is_anonymous %}
  ゲストです
{% else %}
  不明
{% endif %}

{# URL 逆引き #}
&lt;a href=&quot;{% url &apos;myapp:detail&apos; article.id %}&quot;&gt;詳細&lt;/a&gt;

{# static ファイル #}
{% load static %}
&lt;link rel=&quot;stylesheet&quot; href=&quot;{% static &apos;css/style.css&apos; %}&quot;&gt;
&lt;img src=&quot;{% static &apos;img/logo.png&apos; %}&quot; alt=&quot;ロゴ&quot;&gt;

{# パーシャル取り込み #}
{% include &quot;myapp/_card.html&quot; with article=a %}

{# コメント #}
{# 一行コメント #}
{% comment %}
ブロックコメント
複数行
{% endcomment %}

{# CSRF トークン (フォーム必須) #}
&lt;form method=&quot;post&quot;&gt;
  {% csrf_token %}
  ...
&lt;/form&gt;

{# 変数定義 #}
{% with total=cart.items|length %}
  カート: {{ total }} 件
{% endwith %}</code></pre>
<h2>テンプレート継承 (extends + block)</h2>

<p>レイアウト共通化の必須テクニックです。</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-django">{# templates/base.html #}
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;ja&quot;&gt;
&lt;head&gt;
  &lt;meta charset=&quot;UTF-8&quot;&gt;
  &lt;title&gt;{% block title %}サイト名{% endblock %}&lt;/title&gt;
  {% load static %}
  &lt;link rel=&quot;stylesheet&quot; href=&quot;{% static &apos;css/style.css&apos; %}&quot;&gt;
  {% block extra_css %}{% endblock %}
&lt;/head&gt;
&lt;body&gt;
  &lt;header&gt;{% include &quot;_nav.html&quot; %}&lt;/header&gt;
  &lt;main&gt;
    {% block content %}{% endblock %}
  &lt;/main&gt;
  &lt;footer&gt;&copy; 2026&lt;/footer&gt;
  {% block extra_js %}{% endblock %}
&lt;/body&gt;
&lt;/html&gt;</code></pre><pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-django">{# templates/myapp/index.html #}
{% extends &quot;base.html&quot; %}
{% load static %}

{% block title %}記事一覧 | {{ block.super }}{% endblock %}

{% block extra_css %}
  &lt;link rel=&quot;stylesheet&quot; href=&quot;{% static &apos;css/article.css&apos; %}&quot;&gt;
{% endblock %}

{% block content %}
  &lt;h1&gt;記事一覧&lt;/h1&gt;
  &lt;ul&gt;
    {% for a in articles %}
      &lt;li&gt;&lt;a href=&quot;{% url &apos;myapp:detail&apos; a.id %}&quot;&gt;{{ a.title }}&lt;/a&gt;&lt;/li&gt;
    {% endfor %}
  &lt;/ul&gt;
{% endblock %}</code></pre>
<h2>カスタムタグ / カスタムフィルタ</h2>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-python"># myapp/templatetags/myfilters.py
from django import template
register = template.Library()

@register.filter
def yen(value):
    &quot;&quot;&quot;1234 → ¥1,234&quot;&quot;&quot;
    return f&quot;¥{value:,}&quot;

@register.simple_tag
def current_year():
    from datetime import date
    return date.today().year

@register.inclusion_tag(&quot;myapp/_card.html&quot;)
def article_card(article):
    return {&quot;article&quot;: article}</code></pre><pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-django">{# 利用側 #}
{% load myfilters %}

&lt;p&gt;{{ price|yen }}&lt;/p&gt;            {# ¥1,234 #}
&lt;p&gt;&copy; {% current_year %} 会社名&lt;/p&gt;
{% article_card a %}</code></pre>
<h2>セキュリティ — エスケープ</h2>

<p>Django テンプレートは<strong>デフォルトで HTML エスケープ</strong>します:</p>
<pre style="background:#1e293b;color:#e2e8f0;padding:1em;border-radius:6px;overflow-x:auto;line-height:1.5"><code class="language-django">{# context: {"user_input": "<script>alert(1)</script>"} #}

{{ user_input }}
{# → &lt;script&gt;alert(1)&lt;/script&gt; に変換され安全 #}

{{ user_input|safe }}
{# → そのまま <script> として出力される (XSS の可能性、信頼できるデータのみ) #}

{% autoescape off %}
  {{ user_input }}
{% endautoescape %}
{# → ブロック全体でエスケープ無効 #}</code></pre>
<h2>FAQ</h2>

<p><strong>Q: テンプレートが見つからないと言われる</strong><br />
A: <code>settings.py</code> の <code>TEMPLATES.DIRS</code> と <code>APP_DIRS=True</code>、<code>INSTALLED_APPS</code> にアプリが入っているかを確認。</p>

<p><strong>Q: Python のメソッド呼び出しは?</strong><br />
A: 引数なしなら自動呼び出し。<code>{{ user.get_full_name }}</code> (括弧不要)。引数ありはカスタムタグを作る。</p>

<p><strong>Q: Jinja2 を使いたい</strong><br />
A: <code>django.template.backends.jinja2.Jinja2</code> を <code>TEMPLATES</code> に設定すれば併用可能。</p>