Djangoメモ(13) : extendsとblockでテンプレートの継承
A Complete Beginner's Guide to Djangoのチュートリアルを参考にテンプレートを継承してみる。
親テンプレート作成と継承
テンプレートに共通部分がある場合は共通部分を親テンプレートとして定義し、子テンプレートに個別の処理を記述するのがメンテンナンスしやすい。
最初に親テンプレートとなるtemplates/base.htmlを下記内容で新規作成する。
{% load static %}<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{% block title %}Django Boards{% endblock %}</title>
<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
</head>
<body>
<div class="container">
<ol class="breadcrumb my-4">
{% block breadcrumb %}
{% endblock %}
</ol>
{% block content %}
{% endblock %}
</div>
</body>
</html>
{% block %}, {% endblock %}は領域を確保するタグで、子テンプレートでこのblock内のHTMLを置き換えることができる。
{% block title %}Django Boards{% endblock %}のようにデフォルト値を指定することもでき、子テンプレートで何も設定されない場合はこのデフォルト値が使用される。
続いて、親テンプレートを継承するようにtemplates/home.htmlとtemplates/topics.htmlを編集する。
templates/home.htmlは以下の通り。
{% extends 'base.html' %}
{% block breadcrumb %}
<li class="breadcrumb-item active">Boards</li>
{% endblock %}
{% block content %}
<table class="table">
<thead class="thead-dark">
<tr>
<th>Board</th>
<th>Posts</th>
<th>Topics</th>
<th>Last Post</th>
</tr>
</thead>
<tbody>
{% for board in boards %}
<tr>
<td>
<a href="{% url 'board_topics' board.pk %}">{{ board.name }}</a>
<small class="text-muted d-block">{{ board.description }}</small>
</td>
<td class="align-middle">0</td>
<td class="align-middle">0</td>
<td></td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}
最初の行の{% extends 'base.html' %}タグは親テンプレートとしてbase.htmlを継承することを意味している。
そして{% block breadcrumb %}内の<li class="breadcrumb-item active">Boards</li>が親テンプレートの{% block breadcrumb %}に挿入されることになる。
templates/topics.htmlは以下の通り。
{% extends 'base.html' %}
{% block title %}
{{ board.name }} - {{ block.super }}
{% endblock %}
{% block breadcrumb %}
<li class="breadcrumb-item"><a href="{% url 'home' %}">Boards</a></li>
<li class="breadcrumb-item active">{{ board.name }}</li>
{% endblock %}
{% block content %}
<!-- just leaving it empty for now. we will add core here soon. -->
{% endblock %}
{% block title %}タグでデフォルト値から変更しているが、{{ block.super }}で親テンプレートのデフォルト値を再利用できる。結果として、board.nameが"Python"の場合は"Python - Django Boards"になる。これでテンプレートの継承は完了。
ナビゲーションバー追加
ナビゲーションバー(BootstrapのNavbarを利用)を追加するためにtemplates/base.htmlを以下のように編集。
{% load static %}<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{% block title %}Django Boards{% endblock %}</title>
<link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}">
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="{% url 'home' %}">Django Boards</a>
</div>
</nav>
<div class="container">
<ol class="breadcrumb my-4">
{% block breadcrumb %}
{% endblock %}
</ol>
{% block content %}
{% endblock %}
</div>
</body>
</html>
ページにアクセスするとナビゲーションバーが追加されている。
このように共通で使用する要素を親テンプレートに定義すると便利。


参考:フォント変更
チュートリアルではフォント変更をしているのでナビゲーションバーのロゴ部分(.navbar-brand)のフォントを変更してみる。
Google Fontsにアクセスして自分の好きなフォントを選択する。
チュートリアルではPeraltaを使っているがPacificoを使ってみる。

図のように追加方法が表示されるのでtemplates/base.htmlを編集。
<head> <meta charset="utf-8"> <title>{% block title %}Django Boards{% endblock %}</title> <link href="https://fonts.googleapis.com/css?family=Pacifico" rel="stylesheet"> <link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}"> <link rel="stylesheet" href="{% static 'css/app.css' %}"> </head>
css/app.cssを下記内容で新規作成。
.navbar-brand { font-family: 'Pacifico', cursive; }
これでフォントが変わる。

まとめ
- テンプレートの共通部分は親テンプレートにまとめる
{% extends 'base.html' %}は親テンプレートとしてbase.htmlを継承{% block %},{% endblock %}で領域を確保し、子テンプレートで該当ブロックを置き換える{% block %}にはデフォルト値を指定することも可能{{ block.super }}で親テンプレートのデフォルト値を参照可能