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>
</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


コメントを残す

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