今回のテーマは「テンプレートの継承とinclude」です。現時点でtemplate/base/top.htmlはフッダー、ヘッター、サイドバーとコンテンツを全て有する1つのHTMLファイルとして生成されました。しかし、ヘッダー、フッター、サイドバー等は他のページでも使い回すことが想定されるものです。また、ログインページにはサイドバーを出したくないなど、必要に応じて取り込んだり、外したりする部品もあります。このような要望に対してDjangoテンプレートは継承とインクルードという二つの方法でテンプレートを使い回す方法を提供しています。では、実際に見ていきましょう。 ※本ページはstaticファイルを扱うまで読まれた方を対象としています。そのためサンプルソースコードが省略されている場合があります。
テンプレートの継承
まず、templates/base/base.htmlを用意し、ここに全ページで共通して使う部品を配置します。他のページではこのbase.htmlを継承して変更部分のみをはめ込むことにします。base.htmlはこんな感じになります。
templates/base/base.html
{% load static %}
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<meta http-equiv="content-language" content="ja">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
{% block meta_tag %}{% endblock %}
<link href="{% static 'css/semantic.css' %}" rel="stylesheet">
{% block css %}{% endblock %}
<title>
{% block title %}IT学習ちゃんねる{% endblock %}
</title>
</head>
<body>
<div class="ui stackable inverted menu">
<div class="header item">
IT学習ちゃんねる
</div>
<a class="item">
このサイトはなに?
</a>
<div class="right menu">
<a class="item">
Log in
</a>
<a class="item">
Sign up
</a>
</div>
</div>
<div class="ui container" style="min-height:100vh;">
{% block content %}
{% endblock %}
</div>
<div class="ui inverted stackable footer segment">
<div class="ui container center aligned">
<div class="ui horizontal inverted small divided link list">
<a class="item">© 2019 Django学習ちゃんねる(仮)</a>
<a class="item">利用規約</a>
<a class="item">プライバシーポリシー</a>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
<script type="text/javascript" src="{% static 'js/semantic.js' %}"></script>
{% block js %}{% endblock %}
</body>
{% block hogehoge %}{% endblock %}で囲まれた部分の中身をbase.htmlを継承した各テンプレートファイルで作成していきます。templates/base/top.htmlは次のように変更されました。
templates/base/top.html
{% extends 'base/base.html' %}
{% block title %}ITについて切磋琢磨する掲示板 - {{ block.super }}{% endblock %}
{% block content %}
<div class="ui grid stackable">
<div class="eleven wide column">
<div class="ui breadcrumb">
<a class="section">TOP</a>
<i class="right angle icon divider"></i>
<a class="section">category</a>
<i class="right angle icon divider"></i>
<div class="active section">thread</div>
</div>
<div class="ui segment">
<div class="content">
<div class="header"><h3>新着スレッド</h3></div>
<div class="ui divided items">
<div class="item">
<div class="content">
<div class="header">
<a><h4>dummy thread</h4></a>
</div>
<div class="meta">
<span class="name">投稿者名</span>
<span class="date">2019-2-1 00:00</span>
</div>
</div>
</div>
<div class="item">
<div class="content">
<div class="header">
<a><h4>dummy thread</h4></a>
</div>
<div class="meta">
<span class="name">投稿者名</span>
<span class="date">2019-2-1 00:00</span>
</div>
</div>
</div>
<div class="item">
<div class="content">
<div class="header">
<a><h4>dummy thread</h4></a>
</div>
<div class="meta">
<span class="name">投稿者名</span>
<span class="date">2019-2-1 00:00</span>
</div>
</div>
</div>
<div class="item">
<div class="content">
<div class="header">
<a><h4>dummy thread</h4></a>
</div>
<div class="meta">
<span class="name">投稿者名</span>
<span class="date">2019-2-1 00:00</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}
この場合は{% block content %}の中身をtop.htmlで作ってはめ込んでいるんですね。尚、今回{% block meta_tag %}や{% block css %}, {% block js %}等を用意したのはページによって特殊に加えたいMETAタグやCSS,JSが出てくることを想定しているためです。またページタイトルに関しては常にbase.htmlのタイトルをハイフンつなぎで表示する目的でblock.superを使ってbase.htmlのタイトルを呼び出しています。
テンプレートのインクルード
今度はサイドバーも別パート化してみましょう。templates/base/sidebar.htmlとします。
templates/base/sidebar.html
<div class="five wide column">
<div class="ui action input" style="width: 100%;">
<input type="text" placeholder="検索">
<button class="ui button"><i class="search icon"></i></button>
</div>
<div class="ui segment">
<div class="content">
<div class="header"><h4>話題のトピック</h4></div>
<div class="ui relaxed list small divided link">
<a class="item">dummy</a>
<a class="item">dummy</a>
<a class="item">dummy</a>
<a class="item">dummy</a>
<a class="item">dummy</a>
</div>
</div>
</div>
</div>
これをtop.htmlの下から2行目に追加して読み込んでみましょう。top.htmlを修正します。
templates/base/top.html
</div>
+ {% include 'base/sidebar.html' %}
</div>
そうですね。部分的に作ったsidebar.htmlをインクルードするだけです。これで必要な場合のみインクルードすれば使えるように別部品化できました。 見た目に関してはstaticファイルを扱うから変化していません。ただしテンプレートが部品化されたことでより効率的な開発が出来ると思います。
最後に
Djangoのテンプレートにはまだ便利な機能がたくさんありますが、機能を使う際に紹介していければと考えています。クラスベースビューを使ってテンプレートを表示する方法を見ていきたいと思います。
Sponsored Link