みなさんこんにちは、ZeroTerasu(@ZeroTerasu)です。
Djangoでは、アプリ内の”templates”フォルダ内にhtmlファイルを作成し、そのhtmlファイルにviews.pyで作成された様々な情報を渡す場面が多くあります。
ここでは、”templates”フォルダ内のhtmlファイル内で使用されるテンプレートタグについて解説とそれに合わせたviews.pyのコードの記述方法を解説してきます。
テンプレートの役割:HTMLの一部だけを書き換える機能
<テンプレートを組み立てる3種類の要素>
変数:{{ 変数名 }}、タグ:{% タグ名 %}、フィルタ:{{ 値 | フィルタ名 }}
(要素) | (文法) |
・変数 | {{ 変数名 }} |
・タグ | {% タグ名 %} |
・フィルタ | {{ 値 | フィルタ名 }} |
例1:ナビゲーションメニュー・ヘッダー・フッター部分(テンプレート)をパーツとして独立させる
ナビゲーションメニュー・ヘッダー・フッター等各ページで共通するページをそれぞれ独立したパーツとして作成して、各ページではそれぞれのパーツを都度読み込む方法を解説します。
これによって、それぞれのパーツに変更が生じた際に、全ページ編集の必要がなくなり、各パーツを編集すれば全ページに変更が適用されるようになりますので、メンテナンス性向上に繋がります。
手順は以下の通りです。
手順1:各パーツを個別のhtmlファイルとして作成する。
手順2:各ウェブページでそれぞれのパーツを読み込む ※includeタグを用いる。
includeタグ:{% include “パーツのテンプレート名” %}
手順3:CSSを設定する。
例:<navbarの作成>
手順1:各パーツを個別のhtmlファイルとして作成する。
下記ディレクトリのように「_navbar.html」を作成する。
(apps/templates/_navbar.html)
<div class="navbar">
<a href="/">ホーム</a>
<a href="/about">私たちについて</a>
</div>
手順2:各ウェブページでそれぞれのパーツを読み込む ※includeタグを用いる。
(apps/templates/index.html)
<html>
<head>
</head>
<body>
{% include "_navbar.html" %}
<h1>自己紹介</h1>
</body>
</html>
例:<footterの作成>
手順1:各パーツを個別のhtmlファイルとして作成する。
下記ディレクトリのように「_footer.html」を作成する。
(apps/templates/_footer.html)
<div>
<p>Copyright 2015-</p>
</div>
手順2:各ウェブページでそれぞれのパーツを読み込む ※includeタグを用いる。
(apps/templates/index.html)
<html>
<head>
</head>
<body>
{% include "_navbar.html" %}
<h1>自己紹介</h1>
{% include "_footer.html" %}
</body>
</html>
※{% include %}タグを使って呼び出すhtmlファイルに対して、コンテキストを引き渡す方法
{{% include ‘テンプレートhtml’ with 変数名=”任意の値” %}}
※{% include %}タグを使って呼び出すhtmlファイルに対して、コンテキストを引き渡す方法
(apps/templates/_footer.html)
<!-- 「年」の部分を{{変数名}}タグで置換する。呼び出す側のhtmlテンプレートから{{year}}に値が引き渡されるようにする。 -->
<div>
<p>Copyright {{year}}-</p>
</div>
(apps/templates/index.html)
<!-- -->
<html>
<head>
</head>
<body>
{% include "_navbar.html" %}
<h1>自己紹介</h1>
{% include "_footer.html" with year="2020" %} <!-- "2020"が_footer.htmlの{{year}}に引き渡される -->
</body>
</html>
手順3:CSSの設定をする。
次に、CSSの設定をします。手順は以下の通りです。
手順3-1:「static」フォルダの作成 (apps/static)
手順3-2:「style.css」の作成 (apps/static/style.css)
手順3-3:htmlファイルへCSSを読み込ませる
手順3-4:settings.pyにstaticフォルダパスを記述
手順3-2:「style.css」の作成 (apps/static/style.css)
(apps/static/style.css)
.navbar{
background: pink;
}
手順3-3:htmlファイルへCSSを読み込ませる
(apps/templates/index.html)
{% load static %} #<=忘れがちなので要注意
<html>
<head>
<link rel="stylesheet" href="{% static 'style.css' %}">
</head>
<body>
{% include "_navbar.html" %}
<h1>自己紹介</h1>
{% include "_footer.html" %}
</body>
</html>
手順3-4:settings.pyにstaticフォルダパスを記述
STATIC_URL = 'static/'
import os
STATICFILES_DIRS = (
os.path.join(BASE_DIR, "static"),
)
#デフォルトでSTATIC_URL = '/static/'となっているのでこれは触らず,その下に上記を追記します。
#osライブラリのインポートが必要な場合は、上記のようにimport osを記述
#先程作成したstaticディレクトリの場所を教えてあげるようなイメージです。
例2:ベースとなるhtmlファイル(base.html)を作成して新しいページを作成する。
まず、ベースとなるhtmlを作成し、次にそれを継承(extends)して新しいページを作成します。そして、下記コードのようにblockタグで挟まれた部分だけ個別のページ毎に変化させることができます。
extendsタグ:{% extends “ベースとなるテンプレート名” %}
blockタグ:{% block ブロック名 %}個別ページ内容{% endblock %}
<テンプレートを共通化したい>
extendsタグとblockタグ
{% extends "ベースとなるテンプレート名" %}
{% block ブロック名 %}
この中身は使う側で上書きできる
{% endblock %}
まずは、各ページのベースとなるbase.htmlをtemplatesフォルダ内に作成します。
base.htmlの作成 (apps/templates/base.html)
{% load static %}
<html>
<head>
<link rel="stylesheet" href="{% static 'style.css' %}">
</head>
<body>
{% include "_navbar.html" %}
{% block main %}
コンテンツがありません。
{% endblock %}
{% include "_footer.html" %}
</body>
</html>
次に、個別ページを作成していきます。index.htmlというファイル名でbase.htmlが保存されているフォルダと同じtemplatesフォルダに作成します。
(apps/templates/index.html)
{% extends "base.html" %}
{% load static %}
{% block main %}
<h1>ホーム</h1>
<img src="{% static 'welcome.jpg' %} />
{% endblock %}
• 画像を読み込むためには、staticフォルダ内に画像を用意しておく必要がある。
• {% load static %} は、base.htmlで設定していても、index.htmlでも設定する必要がある。
例3:usernameを表示させる。
ここからは、具体的にviewからテンプレート(htmlファイル)に値を渡す方法について説明していきます。
やりたいこと:views.pyからテンプレート(htmlファイル)に値を渡したい
views.pyに「get_context_data」という関数を定義します。
この関数の中の「context」(コード内では、変数ctxtと定義。以下、「context」=「ctxt」とします。)を使って値を渡すことが出来ます。
「ctxt」の要素を「get_context_data」内で変更を加えて、変更後の「ctxt」をhtmlファイルに渡すことで変更内容がhtmlファイルに反映されます。
また、「ctxt」の各要素は、テンプレート(htmlファイル)の中では{{ 変数名 }}で表示できます。
変数名タグ:{{ 変数名 }}
まずは、テンプレートを作成します。
テンプレートに{{ 変数名 }}を定義
(apps/templates/index.html)
{% extends "base.html" %}
{% load static %}
{% block main %}
<h1>{{ username }}さんこんにちは</h1>
<img src="{% static 'welcome.jpg' %} />
{% endblock %}
次に、views.pyを作成します。
views.pyに「get_context_data」を定義する。
(apps/views.py)
from django.views.generic import TemplateView
class IndexView(TemplateView):
template_name = "index.html"
def get_context_data(self):
ctxt = super().get_context_data()
ctxt["username"] = "太郎"
return ctxt
class AboutView(TemplateView):
template_name = "about.html"
• ctxt:開発者の間では一般的な記法。辞書型。
• super():TemplateViewが用意しているUserを規定する変数
• super().get_context_data():TemplateViewが用意しているUserを表す変数からデータを取得している。
例4:テンプレート(htmlファイル)に数字表示変更・リスト作成
例:アドレス帳に登録されている人数と人名をhtmlファイルに表示する。
元々アドレス帳に登録されている件数と分類を表示し、その後アドレス帳に追加した後の情報をhtmlファイルに表示したいと思います。
手順としては下記のようになります。
手順①:元々登録されている情報を基にhtmlファイルを作成する。
手順②:変更を加える箇所を{{ 変数名 }}タグで置換する。
手順③:views.pyで変更内容を定義する。
元々登録されている情報
アドレス帳登録件数:123456名
アドレス帳分類:家族、仕事、趣味
追加後に登録されている情報
アドレス帳登録件数:12345678名
アドレス帳分類:家族、仕事、趣味、町内会、役所、携帯ショップ
下記の例では、まずアドレス帳登録件数の変更のコードを記述します。
テンプレート(htmlファイル)の数字表示変更の例
手順①:address.htmlに元々の登録内容を入力する
(apps/templates/address.html)
{% extends "base.html" %}
{% load static %}
{% block main %}
<h1>アドレス帳</h1>
<h2>登録件数</h2>
<p>これまでに123456件のアドレスが登録されていました。</p>
<h2>分類</h2>
<ul>
<li>家族</li>
<li>仕事</li>
<li>趣味</li>
</ul>
{% endblock %}
手順②:address.htmlの変更を加える箇所を{{ 変数名 }}タグで置換する。
(apps/templates/address.html)
{% extends "base.html" %}
{% load static %}
{% load humanize %}
{% block main %}
<h1>アドレス帳</h1>
<h2>登録件数</h2>
<p>これまでに{{ num_registration|intcomma }}件のアドレスが登録されていました。</p>
<h2>分類</h2>
<ul>
<li>家族</li>
<li>仕事</li>
<li>趣味</li>
</ul>
{% endblock %}
• humanizeはsetting.py => INSTALLED_APPSに追加する必要がある。
'django.contrib.humanize'
手順③:views.pyで変更内容を定義する。
(apps/views.py)
from django.views.generic import TemplateView
class AboutView(TemplateView):
template_name = "address.html"
def get_context_data(self):
ctxt["num_services"] = 12345678
return ctxt
続いて、アドレス帳の分類を追加したいと思います。views.pyでリストを作成して、htmlでfor文を使って要素を追加していく方法を使います。
テンプレート(htmlファイル)のリスト作成の例
リスト作成方法
リスト作成方法の概要
htmlファイルにおいて下記のように記述する。
<リストの中身を順番に繰り返して表示したい>
for/empty文
{% for アイテム in リスト %}
アイテムを表示する
{% empty %}
リストが空の場合表示される
{% endfor %}
現在時刻を表示する = {% now %}の活用
手順②:address.htmlの変更を加える箇所を{{ 変数名 }}タグで置換する。
(apps/templates/address.html)
{% extends "base.html" %}
{% load static %}
{% load humanize %}
{% block main %}
<h1>アドレス帳</h1>
<h2>登録件数</h2>
<p>{% now "Y年m月d日 H時i分" %}現在までに{{{ num_registration|intcomma }}件のアドレスが登録されていました。</p>
<h2>分類</h2>
<ul>
{% for classification in classifications %}
<li>{{ classification }}</li>
{% empty %}
<li>分類がありません。</li>
</ul>
{% endblock %}
• humanizeはsetting.py => INSTALLED_APPSに追加する必要がある。
'django.contrib.humanize'
手順③:views.pyで変更内容を定義する。
(apps/views.py)
from django.views.generic import TemplateView
class AboutView(TemplateView):
template_name = "address.html"
def get_context_data(self):
ctxt["num_services"] = 12345678
ctxt["classifications"] = [
"家族",
"仕事",
"趣味",
"町内会",
"役所",
"携帯ショップ"
]
return ctxt
例5:アクセスユーザーの種類によってユーザー名を表示し分ける
次に、ユーザーに応じて表示内容を変更する方法を解説致します。まずは、Djangoにおける条件分岐の構文を紹介します。
Djangoにおける条件分岐
htmlファイルにおいて下記のようなコードを入力する。
<条件によって表示する内容を変えたい>
if/elif/else
{% if 条件1 %}
条件1が満たされたときにここが表示される。
{% elif 条件2 %}
条件2が満たされたときにここが表示される。
{% else %}
どの条件も満たされなかったときにここが表示される。
{% endif %}
それでは、実際にhtmlファイルとviews.pyを作成していきます。
手順①-②:index.htmlに都度変更を加える箇所を{{ 変数名 }}タグで置換する。
(apps/templates/index.html)
{% extends "base.html" %}
{% load static %}
{% load humanize %}
{% block main %}
{% if username == "自分の名前" %}
<h1>自分です。</h1>
{% elif username %}
<h1>{{ username }}さん、ようこそ!</h1>
{% else %}
<h1>匿名さん、ようこそ!</h1>
{% endblock %}
手順②:address.htmlの変更を加える箇所を{{ 変数名 }}タグで置換する。
(apps/templates/address.html)
{% extends "base.html" %}
{% load static %}
{% load humanize %}
{% block main %}
<h1>アドレス帳</h1>
<h2>登録件数</h2>
<p>これまでに{{ num_registration|intcomma }}件のアドレスが登録されていました。</p>
<h2>分類</h2>
<ul>
<li>家族</li>
<li>仕事</li>
<li>趣味</li>
</ul>
{% endblock %}
• humanizeはsetting.py => INSTALLED_APPSに追加する必要がある。
'django.contrib.humanize'
手順③:views.pyで変更内容を定義する。
(apps/views.py)
from django.views.generic import TemplateView
class IndexView(TemplateView):
template_name = "index.html"
def get_context_data(self):
ctxt = super().get_context_data()
ctxt["username"] = "太郎"
return ctxt
class AboutView(TemplateView):
template_name = "about.html"
• ctxt:開発者の間では一般的な記法。辞書型。
• super():TemplateViewが用意しているUserを規定する変数
• super().get_context_data():TemplateViewが用意しているUserを表す変数からデータを取得している。
TIME_ZONEの編集
settings.pyのデフォルトでは、TIME_ZONE = ‘UTC’となっています。TIME_ZONE = ‘ASIA/TOKYO’に変更すると日本時間で表示されるようになります。
footerの年を変更
<div>
<p>Copyright 2015-{% now "Y"%}</p>
</div>
コメント