このページでは、Djangoのテンプレートシステムにおける1つの核心的な概念「テンプレートの継承」について詳しく説明します。
テンプレートの継承とは、一言で言うと、既存のテンプレート(通常はベースとなるテンプレート)から特定の部分を再利用し、その上で新たな要素を追加したり、既存の要素をオーバーライド(上書き)したりすることを可能にする機能です。
このページでは、テンプレートの継承とは何か?そのメリットと使用方法、さらには実践的な例とベストプラクティスを含む具体的な応用例を紹介します。
Djangoを用いたWeb開発を行いたい人であれば、知らないと恥ずかしい超・基本知識の1つです。是非最後までご覧ください。
Django:テンプレートの継承とは
テンプレートの継承とは、あるテンプレート(一般的にはベーステンプレートと呼ばれます)が持つ一部または全部の構造や要素を再利用し、新たなテンプレートを作る方法を指します。
例えば、画面のヘッダーやフッターを定義するベーステンプレートを用意しておいて、そのテンプレートをもとに、ヘッダーやフッターだけを編集した別のテンプレートを作るようなイメージ。
これは、DjangoがDRY(Don't Repeat Yourself)というコーディング原則を反映したもので、同じコードを何度も書く必要を減らし、保守性と効率性を向上させるための機能の1つ。
テンプレートの継承を理解するために、以下の2点について学習していきます。
- 基底テンプレートの作成: Djangoのテンプレートシステムでは、ベースとなるテンプレートを作成し、その中に再利用したいHTMLの構造や要素を定義。ナビゲーションバー、フッター、スタイルシートのリンク、スクリプトのリンクなど、複数のページで共有される要素を含みます。
- ブロックの定義とオーバーライド: ベーステンプレートには、子テンプレートでオーバーライド(上書き)または追加できるブロックを定義します。これらのブロックは、ページタイトル、メインコンテンツ、追加のスタイルシートなど、ページによって異なる可能性のある部分を占めます。
上記2点についてステップバイステップで解説していきます。
ベーステンプレートの作成
まず、ベース(親)テンプレートを作成します。このベーステンプレートには、すべてのテンプレートから共有される「共通のHTML構造」を定義します。
参考 HTMLとは?
以下がベーステンプレート(base.html
)の例です。
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>{% block title %}デフォルトタイトル{% endblock title %}</title> <!-- その他のメタ情報、スタイルシートのリンクなど --> </head> <body> <header> <!-- ヘッダーの内容 --> </header> <main> {% block content %} <!-- この部分は子テンプレートでオーバーライドされます --> {% endblock content %} </main> <footer> <!-- フッターの内容 --> </footer> <!-- その他のスクリプトなど --> </body> </html>
参考 HTMLの基本構造・書き方 / <header>タグ /<main>タグ
ここでは{% block title %}
と{% block content %}
の2つのブロックを定義しています。これらは子テンプレートでオーバーライドすることができます。
ここで、blockタグについて詳細を補足します。
Django:blockタグ
block
はテンプレート内で再利用可能なセクションを定義するためのタグです。ベーステンプレートでは block
を使用して子テンプレートで上書き(オーバーライド)できるセクションを定義します。
{% block blockname %} Default content... {% endblock %}
blockname
はブロックの名前(任意の名前)で、Default content...
はブロックのデフォルトコンテンツ(子テンプレートでオーバーライドされない場合に表示される部分)です。
このblockタグを利用した部分は、次に解説する子テンプレートで上書きをすることが可能になるということです。
子テンプレートの作成とベーステンプレートからの継承
次に、ベーステンプレートから継承する子テンプレートを作成します。
子テンプレートでは、{% extends "base.html" %}
を使用して基底テンプレートから継承を行い、{% block %}
タグを使用して基底テンプレートのブロックをオーバーライドします。
{% extends "base.html" %} {% block title %}マイページ{% endblock title %} {% block content %} <h1>ようこそ、マイページへ!</h1> <!-- その他のコンテンツ --> {% endblock content %}
参考 hタグ
この子テンプレートでは、基底テンプレートのtitle
ブロックとcontent
ブロックをオーバーライドしています。
分かりやすく言うと、1行目のextendsタグで「base.html」をテンプレートにするよ!と宣言。
そして、blockタグで「この部分はこの内容で上書きするよ!」という処理を書いています。
具体的なサンプルコードを見てみましょう。
例えば、以下のようなベーステンプレートがあるとします。
<!DOCTYPE html> <html> <head> <title>{% block title %}デフォルトタイトル{% endblock %}</title> </head> <body> <header> <nav> <!-- ナビゲーションメニュー --> </nav> </header> <main> {% block content %} <!-- デフォルトコンテンツ:子テンプレートでオーバーライド予定 --> {% endblock %} </main> <footer> <!-- フッター情報 --> </footer> </body> </html>
参考 navタグ
このテンプレートをもとに、{% block %}
タグを使ってベーステンプレートのブロックをオーバーライド↓。
{% extends "base.html" %} {% block title %} マイページ {% endblock %} {% block content %} <h1>ようこそ、マイページへ!</h1> <p>ここは、ユーザーのマイページです。</p> {% endblock %}
参考 pタグ(段落タグ)
こうすることで、ベーステンプレートをもとにして、必要な部分だけを上書きした画面が出来上がるというわけです。
継承するHTMLファイルの指定
Djangoではextends
タグを使って他のテンプレートを継承する際、テンプレートファイルの位置はTEMPLATES
設定のDIRS
オプションに指定されたディレクトリが検索対象となります。
つまり、extends
で指定するテンプレートファイルは同じフォルダに存在する必要はありません。
通常、Djangoプロジェクトはプロジェクト全体のテンプレートを配置するためのtemplates
ディレクトリを持ち、各アプリケーションディレクトリの下にも各々templates
ディレクトリを持つ構造になっています。
myproject/ ├── manage.py ├── myproject/ │ ├── __init__.py │ ├── settings.py │ ├── urls.py │ ├── wsgi.py ├── templates/ │ ├── base.html └── todo/ ├── __init__.py ├── admin.py ├── apps.py ├── migrations/ ├── models.py ├── templates/ │ ├── todo/ │ │ ├── index.html │ │ ├── task_form.html │ │ └── delete_confirm.html ├── tests.py ├── urls.py └── views.py
ここで、各アプリケーションディレクトリ(↑の例言えば「todo
」)の下にあるtemplates
ディレクトリには、そのアプリケーション専用のテンプレートを配置。
プロジェクト全体で共有するテンプレート(↑の例で言えば「base.html
」)はプロジェクトレベルのtemplates
ディレクトリに配置します。
settings.py
のTEMPLATES
設定ではDIRS
オプションにプロジェクトレベルのtemplates
ディレクトリのパスを含めます。
# settings.py TEMPLATES = [ { ... 'DIRS': [BASE_DIR / 'templates'], # BASE_DIRはプロジェクトのルートディレクトリを表す ... }, ]
このようにすることで、base.html
のようなプロジェクト全体で共有するテンプレートを各アプリケーションから参照することが可能になります。
したがって、todo
アプリケーションのindex.html
からbase.html
を継承するには、以下のように記述すればOKということ。
{% extends 'base.html' %} ...
extends
タグで指定するテンプレートファイルの位置は、TEMPLATES
設定のDIRS
オプションで指定されたディレクトリの下であればどこでもかまいません。
Django:extends/blockのまとめ
初めてPythonを勉強するのは結構難しいですよね。
でもその悩みを抱えているのは一人じゃありません。全てのPython使いが同じ道を進んできました。
Pythonをはじめとするプログラミングスキルを武器に、時間と場所に捉われない自由な生き方を目指してみませんか?今すぐ行動したい方は以下の記事をチェック!
読者料典 Python入門:学習カリキュラム ←こちらから!