本文へスキップ
BecomeCoder

Djangoコース · 第3章 テンプレート · レッスン13

テンプレート継承 ― {% extends %} と {% block %}

ブラウザで完結

導入

サイトの全ページで、ヘッダー・フッター・メニューは同じ。それを毎回コピーするのは悪夢です。Django のテンプレート継承は、共通の骨組みを「親テンプレート」に1回だけ書き、各ページは違うところ(block)だけを埋めます。

説明

親テンプレートに {% block 名前 %}{% endblock %} で「差し替え可能な穴」を用意し、子テンプレートで {% extends %} して穴を埋めます。ここでは複数の名前付きテンプレートを扱うため、render(request, "ページ名", {...}) の形(本物のプロジェクトと同じ)を使います。

import django
from django.conf import settings
if not settings.configured:
    settings.configure(DEBUG=True, SECRET_KEY="dev",
        ROOT_URLCONF=__name__, ALLOWED_HOSTS=["testserver"],
        TEMPLATES=[{
            "BACKEND": "django.template.backends.django.DjangoTemplates",
            "OPTIONS": {"loaders": [("django.template.loaders.locmem.Loader", {
                # 親テンプレート:共通の骨組み。block が差し替え可能な穴。
                "base.html": (
                    "<html><body>"
                    "<header>My Site</header>"
                    "<main>{% block content %}{% endblock %}</main>"
                    "<footer>(c) 2026</footer>"
                    "</body></html>"
                ),
                # 子テンプレート:base を継承し、content だけを埋める。
                "home.html": (
                    "{% extends 'base.html' %}"
                    "{% block content %}<h1>ようこそ {{ name }} さん</h1>{% endblock %}"
                ),
            })]},
        }])
    django.setup()

from django.shortcuts import render
from django.urls import path
from django.test import Client

def home(request):
    return render(request, "home.html", {"name": "Aki"})

urlpatterns = [path("", home)]

client = Client()
print(client.get("/").content.decode())

出力を見ると、home.html には content しか書いていないのに、base.html のヘッダー・フッターに囲まれた完全な HTML になっています。これが継承の力です。

  • {% block content %}{% endblock %} … 親が用意する「穴」。
  • {% extends 'base.html' %} … 子の先頭に書き、「この親を土台にする」宣言。
  • render(request, "home.html", {...}) … ビューでテンプレートを描画する定番の書き方。第3引数の辞書が Context になります。

やってみよう

base.html<nav>メニュー</nav> を足すと、home.html を変えなくても全ページにメニューが増えます。共通部分を1か所で管理できるのが継承の利点です。render に渡す {"name": "..."} を変えると、見出しの名前が変わります。

演習

base.htmlcontent ブロックの前に、差し替え可能な {% block title %}無題{% endblock %}<h1> として足し、home.html 側で {% block title %}ホーム{% endblock %} を定義してください。出力に ホーム が含まれれば成功です。

ヒント1を見る

親:<h1>{% block title %}無題{% endblock %}</h1><main> の前に置きます。

ヒント2を見る

子:{% block title %}ホーム{% endblock %}{% extends %} の後に追加します。

実際に動かしてみよう

本文のサンプルや演習のコードは、コードブロック右上の「コピー」ボタンでコピーして、下のエディタに貼り付ければそのまま実行できます。

Python — ライブラリ付きで実行(Pyodide)

numpy / pandas / matplotlib が使える本物のPython(Pyodide)を読み込みます。初回のみ読み込みに少し時間がかかります(以降はブラウザにキャッシュされます)。
スクロールして表示された時点でも自動で読み込まれます。