テンプレートタグの使い方

5.5 テンプレートタグの使い方

Templateの基本は、「値を出力する(表示する)」ということですが、それ以外の事前にDjangoで組み込まれた機能としてテンプレート(組み込み)タグが用意されています。

5.5.1 テンプレートタグを使ってみよう

テンプレートタグを用いることで、Pythonの組み込み関数やif文、for文などの機能をテンプレートファイルで用いることができ、テンプレートタグは、{%○○%}という形で使用できます。

ここでは先ほど作成したhowto.htmlを開き、<div class=”contents”>タグの部分をこのように書き換えてみてください。

【ファイル名:howto.html】

1<div class="contents">
2 
3    <h2>テンプレートタグを使ってみよう</h2>
4    <p> {% now "" %} </p>
5 
6</div>

以下のアドレスからアプリケーションにアクセスします。
URL:http://localhost:8080/loginform/template

図 5.5 1:Templateの色々な使い方

5.5.2 テンプレートタグ一覧

テンプレートタグは「now」以外にも沢山あります。既に使用したテンプレートタグもありますが、以下ではよく使われるテンプレートタグの一覧をまとめました。

参照:組み込みタグとフィルタ(https://docs.djangoproject.com/ja/1.11/ref/templates/builtins/)

テンプレートタグの基本的な使い方について説明したところで、以下でより具体的なテンプレートタグの使い方について確認していきましょう。

5.5.3 includeタグ

Webページは、常に1つのファイルだけで作成しなければいけないわけではありません。例えば、ヘッダーやフッター、メニューといった部品を別ファイルとして用意し、それらを組み合わせてページ全体のレイアウトを作成する、ということもよくあります。

Templateで、このように「複数のファイルを組み合わせてページを構成する」ということを行ないたい場合、利用されるのが「includeタグ」です。これは、あるファイルの中に「フラグメント」(そこだけ切り取って扱えるようにした部品)として記述されている部分を、別のTemplateの指定した場所にはめ込む技術です。
これは、部品となるファイルと、それを組み込む側の両方を用意する必要があります。簡単に整理しておきましょう。

まず部品となるファイルは通常のhtmlファイルをtemplatesフォルダ内に用意します。その上で組み込む側のテンプレートファイル内の任意の場所に以下のタグを入力します。

includeタグを記述した場所に組み込まれます。

では、実際にやってみましょう。まずは、新たにテンプレートファイルを用意しましょう。

  1. 「templates」内に「fragment.html」を作成
  2. 1で作成した「fragment.html」ファイルに以下に示すソースコードを記述する。

【ファイル名:fragment.html】

1<!DOCTYPE html>
2<html>
3<head>
4    <meta charset="UTF-8">
5    <title>テンプレートフラグメント</title>
6    <style>
7        .contents {
8            width: 80%;
9            margin: 0 auto;
10        }
11        h2 {
12            margin-top: 2em;
13            border-bottom: 1px solid black;
14        }
15    </style>
16</head>
17<body>
18    <div>
19        <p>これはフラグメントコンテンツです。</p>
20        <p>サンプルメッセージ</p>
21    </div>
22</body>
23</html>

続けて、テンプレート側の修正も行ないます。

【ファイル名:howto.html】

1<!DOCTYPE html>
2<html>
3<head>
4    <meta charset="UTF-8">
5    <title>Templateの色々な使い方</title>
6    <style></style>
7</head>
8<body>
9    <div class="contents">
10        <h2>テンプレートフラグメント</h2>
11        {% include 'fragment.html' %}
12    </div>
13</body>
14</html>

以下のアドレスからアプリケーションにアクセスします。
URL:http://localhost:8000/loginform/template/

図 5.5 2:fragment.htmlに用意したフラグメントがページ内に組み込まれた形で表示される

【ファイル名:howto.html】

組み込む側(howto.html)の10行目で「{% include ‘fragment.html’ %}」と指定していますが、指定した箇所に「fragment.html」の内容が反映されているのがわかります。

5.5.4 条件分岐のifタグ

続いてTemplate内で条件分岐を使用する方法について確認していきましょう。条件分岐をTemplate内で活用するためにはifタグを使用します。

まずは、基本的な構文から見ていきます。

1{% if 条件文 %}
2<!-- if 文内の処理 -->
3{% elif 条件文 %
4<!-- elif 文内の処理 -->
5{% else %
6<!-- else文内の処理  -->
7{% endif %}

通常のif文と同じく、それぞれ条件がtrueだった場合、自身のブロック(範囲)のプログラムが実行、または表示されます。
実行されるブロックの範囲は、次のelif文({% elif 条件文 %})、else文({% else %})、または終了タグ({% endif %})までが範囲となります。
またelif文、else文は省略できますが、通常のpythonのプログラムと違い、ブロックが明確ではないのでif文の最後に終了タグ({% endif %})を記載しなければなりません。

ではパラメータ値の内容に合わせて表示が変わるよう、以下のようにファイルを修正してください。

【ファイル名:howto.html】

以下のアドレスからアプリケーションにアクセスします。

URL:http://localhost:8000/loginform/template/?param=11

図 5.5 3:パラメータ値によって表示を変える

URL:http://localhost:8000/loginform/template/?param=6

図 5.5 4:パラメータ値によって表示を変える

URL:http://localhost:8000/loginform/template/?param=2

図 5.5 5:パラメータ値によって表示を変える

パラメータ値によって表示内容が変わりましたね。

「views,py」の24行目では、パラメータ値を取得するとStr型として処理されるため、int関数を使って整数に変換しています。

5.5.5 繰り返しのforタグ

条件分岐があるなら、当然、繰り返しのための属性もあります。これはテンプレートタグで、以下のように記述します。

1{% for カウンタ変数 in リストなどのイテラルオブジェクト %}
2    ……{{カウンタ変数}}を利用した表示……
3{% endfor %}

リストなどのイテラルオブジェクトにはViewで用意した値を格納します。
ではView(views.py)、Template(howto.html)の修正をしていきましょう。

【ファイル名:views.py】

【ファイル名:howto.html】

以下のアドレスからアプリケーションにアクセスします。
URL:http://localhost:8000/loginform/template/

図 5.5 6:データの一覧が表示される

まず、View側から見ていきます。ここではリストを作成し、各要素に Userインスタンスを保管しています。これをTemplate側に users として渡し、表示させようというわけです。

【ファイル名:views.py】

テンプレート側では<table>タグの部分を見てみましょう。

【ファイル名:howto.html】

Viewで用意したリストをusersとして受け取り、for文内では各要素をカウンタ変数userとして順に値を取り出し、繰り返し処理が実行されます。
またusersの各要素であるuserはUserクラスのインスタンスですので、name属性、age属性の取得には、getName、getAgeを使用します。

5.5.6 HTMLコードの出力

ここまでは、すべてテキストを出力させるだけでした。では、テキストではなく、HTMLのコードをそのまま出力させたい場合はどうするのでしょうか。早速試してみましょう。

【ファイル名:views.py】

【ファイル名:howto.html】

以下のアドレスからアプリケーションにアクセスします。
URL:http://localhost:8000/loginform/template/

図 5.5 7:HTMLコードをそのまま出力する

出力結果から、9行目のようにViewから受け取った値をそのまま出力するとHTMLコードが画面上に表示されますが、10~12行目のように{% autoescape off %}~{% endautoescape%}タグで囲われた状態で出力すると、HTML処理された状態で出力されます。

【ファイル名:howto.html】

1<p>{{ html }}</p>
2{% autoescape off %}
3<p>{{ html }}</p>
4{% endautoescape %}

このようにDjangoではデフォルトではViewで用意した値をエスケープ処理した状態でTemplateに引き渡されます。
反対にアンエスケープ(エスケープしない)テキストを出力するためには、 {% autoescape off %}~{% endautoescape %}タグで囲った状態で出力する必要があります。

■HTMLタグをエスケープする重要性

先ほどの{% autoescape off %}タグは、HTMLタグを出力する際には非常に役立ちます。が、これは「値にHTMLタグが含まれていると、それがそのまま機能してしまう」ということですから、出力される値の内容に問題があればトラブルの要因となるでしょう。特に、ユーザーから送信された情報を元にテキストを作成する場合、XSS(cross site scripting)などの攻撃に対し無力になってしまいます。そのあたりの危険を理解した上で利用しましょう。

5.5.7 urlタグ

既に「urls.py」に登録されているURLを絶対パスで取得できるurlタグについて、基本的な使用方法を説明しました。

ここではもう少し応用的な使用例を以下で試していきましょう。

■ソースコード
【ファイル名:LoginForm/urls.py】

■ソースコード
【ファイル名:views.py】

【ファイル名:howto.html】

以下のアドレスからアプリケーションにアクセスします。

URL:http://localhost:8000/loginform/template/6

図 5.5 8:リンクには、/template/6というようにViewから渡された値が追加される

ここでのポイントは「urls.py」に登録されている7行目の箇所です。

【ファイル名:LoginForm/urls.py】

1path('template/<int:id>', views.Template,name="template"),

7行目を確認すると「template/●●●」の形式のURLにアクセスすると(※●●●はint型)、Template関数が読み込まれます。

Template関数では、引数idに「’template/<int:id>」の「id」が合致するので、今回のケースでは「/template/6」の「6」が引数idに格納されます。

【ファイル名:views.py】

またidの値はキー名が「id」としてTemplate(howto.html)に引き渡されます。

「howto.html」を確認すると「{% url ‘template’ id %}」と記載されています。
【ファイル名:howto.html】

「urls.py」を確認すると「template/●●●」に対して「name=”template”」となっているので、「{% url ‘template’ id %}」と記載することで、「http://localhost:8000/loginform/template/●●●」が表示されることがわかります。
【ファイル名:LoginForm/urls.py】

1path('template/<int:id>', views.Template,name="template"),

また{% url ‘template’ id %}のidは、「template/<int:id>」の「<int:id>」の箇所に合致します。idは、Viewから渡された値(6)ですので、「{% url ‘template’ id %}」により「http://localhost:8000/loginform/template/6」が取得できます。


NEXT>> 5.6 本章のまとめ

f