導入
サイトの全ページで、ヘッダー・フッター・メニューは同じ。それを毎回コピーするのは悪夢です。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.html の content ブロックの前に、差し替え可能な {% block title %}無題{% endblock %} を <h1> として足し、home.html 側で {% block title %}ホーム{% endblock %} を定義してください。出力に ホーム が含まれれば成功です。
ヒント1を見る
親:<h1>{% block title %}無題{% endblock %}</h1> を <main> の前に置きます。
ヒント2を見る
子:{% block title %}ホーム{% endblock %} を {% extends %} の後に追加します。