1-6. テンプレートの継承とinclude

今回のテーマは「テンプレートの継承と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>
    {% include 'base/sidebar.html' %}
</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行目に追加して読み込んでみましょう。
templates/base/top.html



     </div>
+    {% include 'base/sidebar.html' %}
 </div>

そうですね。部分的に作ったsidebar.htmlをインクルードするだけです。これで必要な場合のみインクルードすれば使えるように別部品化できました。

見た目に関してはstaticファイルを扱うから変化していません。ただしテンプレートが部品化されたことでより効率的な開発が出来ると思います。

最後に

Djangoのテンプレートにはまだ便利な機能がたくさんありますが、機能を使う際に紹介していければと考えています。クラスベースビューを使ってテンプレートを表示する方法を見ていきたいと思います。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です