[Django]blockタグについて。{{ block.super }}も理解する
Djangoのテンプレートでは色々なタグ(if,for,extendsなどなど)を使うことができますが、その中でもblockタグについて紹介します。
よく使うタグですが、知識の整理も兼ねて紹介。
Djangoのblockタグとは?
Djangoのテンプレートでは、あらかじめ用意されたテンプレートタグというものを利用することができ、テンプレートの機能を拡張することができます。
その中のblockタグでは、継承関係のある子テンプレートからオーバーライド(上書き)ができるタグになります。
例えば、base.htmlという親テンプレートの特定の部分を子テンプレートで定義したものに差し替えることができます。
例えばブログやメディアのようなアプリケーションを作った時に、共通部分(ヘッダやフッタなど)をbase.htmlに記述し、それ以外の中身はそれぞれのファイルに書き分けることでスッキリ記述することができます。
<!doctype html> <html lang="ja"> <head> <meta charset="utf-8"> <title>{% block title %}title{% endblock %}</title> </head> <body> {% block content %} {% endblock %} </body> </html>
↑base.htmlの一例。bootstrapやjquey、cssを読み込んだりなどなどの基本テンプレートを記述。
{% extends 'アプリケーション名/base.html' %} {% block content %} {% for post in posts %} <div> <h2>{{ post.title }}</h2> </div> {% endfor %} {% endblock %}
↑継承した子テンプレート。{% extends ~~~ %}と記述し、blockタグの中にコンテンツの中身を書いていきます。block contentで記載した部分を、base.htmlのblock contentに挿入します。
つまり、前述した
blockタグでは、継承関係のある子テンプレートからオーバーライド(上書き)ができるタグになります。
というわけです。親テンプレートのblock content内を空にしておいて、そこに子テンプレートで記述した部分を挿入(上書き)しています。
イメージとしては、子テンプレート→親テンプレートとなります。
blockのあとはどんな名前でも良い
ちなみに、blockタグのあとに続く名前は任意です。
先ほどの例やDjangoチュートリアルでは{% block content %}をよく見かけますが、{% block hoge %}でもOKです。その場合、拡張先の子テンプレートでも名前を一致させます。
<body> {% block hoge %} {% endblock %} </body>
hogeだと分かりつらいので実用的ではないですけど、例えばblcok sidebarやblock ad(広告)などその内容に適した名前を付けると見通しもよくなると思います。
{{ block.super}}とは?
そしてblockタグには{{ block.super }}なるものもあります。
{{ block.super }}は親テンプレートのブロック内部の値を持った変数になります。そして、それを子テンプレートで使えるようになります。
こういうことですね。
# 親テンプレート {% block test %} <p>タコス食べたい</p> {% endblock %}
# 子テンプレート {% extends 'base.html' %} {% block test %} <p>今日のランチは、</p> {{ block.super}} {% endblock %}
親テンプレートのblockタグ内で記述したコードを変数として保持し、子テンプレートで展開することができます。
通常のblockタグが子テンプレート→親テンプレートというものですが、block.superは親テンプレートから子テンプレートへの継承のようなイメージです。
{{ block.super }}をこう使った
blockタグさえ抑えておけばまあ足りるでしょ、と思っていましたがDjangoアプリケーションを作成していると意外に親から子への継承も欲しいと思う場面がありました。
私はシェアボタン で使いました。
トップページ(記事一覧ページ)、記事詳細ページ、カテゴリーページ、固定ページと複数のページを持つアプリケーションを作成していました。
ヘッダーやフッターなど全ページ共通部分はbase.htmlで書いて全てのページで反映させていましたが、記事詳細ページと固定ページのみにシェアボタンを設定したいと思いました。
最初はそのまま各ページのhtmlに記述していましたが、今後シェアボタン を置くページが増えると変更が面倒だなと。
かと言ってblockタグで記述すれば全ページに反映されるな・・・とも。
そこで、{{ block.super }}の出番です。base.html(親テンプレート)にシェアボタン を記述し、シェアボタン を設置したいページだけに{{ block.super }}を展開すればいいだけです。
シェアボタン のデザイン変更があってbase.html(親テンプレート)だけを修正すればいいので楽になりました。