Flask入門|テンプレートマクロの基本と実践方法【チャプター4-06】

一つ前のページではカスタムバリデータについて学習しました。
今回は テンプレートマクロ について見ていきましょう。
Chapter1:Flask入門編
Chapter2:Jinja2入門編
Chapter3:フィルター編
Chapter4:フォーム編
・Chapter4-1:HTTPとは何か
・Chapter4-2:フォームの基本を理解しよう
・Chapter4-3:WTFormsを理解しよう
・Chapter4-4:フォームのバリデーションを理解しよう
・Chapter4-5:カスタムバリデータを理解しよう
・Chapter4-6:テンプレートマクロを理解しよう ◁今回はここ
・Chapter4-7:Flask-WTFを理解しよう
Chapter5:データベース編
Chapter6:Flaskの便利機能編
Chapter7:アプリ開発編
Flaskでアプリケーションを作っていくと、HTMLテンプレートの中で同じようなコードを何度も書くことが出てきます。
たとえばフォームの入力欄やボタンなど、見た目や処理が似たような部分が増えるとどんどんテンプレートが長くなり、管理が大変になります。
そんなときに役立つのが「テンプレートマクロ」です。
マクロを使えば共通パターンをテンプレートの中に一つの「部品」として定義しておくことができ、それを繰り返し使い回すことができます。
これによりテンプレートがすっきりし、保守性も高まります。
本記事は 有料記事(100円)ですが、現在は期間限定で無料公開中です。
Flaskで使うテンプレートマクロの基礎と書き方
「マクロ(macro)」という言葉には「何かを簡略化してくれる仕組み」といった意味があります。
Flaskで使われるJinja2テンプレートでもこの「マクロ」を使うことができます。
テンプレートマクロとは、HTML内で何度も使いたいコードのパターンを1つの「関数のようなもの」として定義し、必要な場所で呼び出すための仕組みです。
特にフォームのフィールド表示など、複雑で繰り返しがちな部分に活用すると非常に便利です。
テンプレートマクロの基本構文を理解しよう
テンプレートマクロを定義するには以下のような構文を使います。
{% macro マクロ名(引数1, 引数2, ...) %} <!-- マクロの中身(HTMLコードなど) --> {% endmacro %}
そして定義したマクロは次のようにして呼び出します。
{{ マクロ名(引数1, 引数2, ...) }}
例えば名前を表示するだけの簡単なマクロを作ってみましょう。
<!-- テンプレートマクロの定義 --> {% macro hello(name) %} <p>こんにちは、{{ name }}さん!</p> {% endmacro %} <!-- 呼び出し --> {{ hello("佐藤") }}
このよう「同じようなコード」を部品として定義しておけば、テンプレート内の記述を短く、そして柔軟に保つことができます。
フォームUIを簡略化するマクロの実用例
では、実際にマクロがどのように使えるのか、フォーム入力欄を例に見てみましょう。
以下は、WTFormsを使ってフォームを構築しているテンプレートを対象とした例です。
<!-- render_fieldという名前のテンプレートマクロの定義 --> {% macro render_field(field, label_text) %} <div class="form-group"> <label>{{ label_text }}</label> {{ field(class="form-control") }} {% if field.errors %} <ul class="error-list"> {% for error in field.errors %} <li>{{ error }}</li> {% endfor %} </ul> {% endif %} </div> {% endmacro %}
他のテンプレートから呼び出す場合は以下のように書きます。
<!-- _macro.htmlで定義されたrender_fieldというマクロを使用する宣言 --> {% from "_macro.html" import render_field %} <form method="POST"> <!-- render_fieldマクロの呼び出し --> {{ render_field(form.username, "ユーザー名") }} {{ render_field(form.password, "パスワード") }} {{ form.submit() }} </form>
macro
はテンプレート内の「関数」と考えると分かりやすいです。field
にはWTFormsのフィールドを、label_text
には表示するラベル名を渡しています。- エラーメッセージが存在する場合は、自動でリストとして表示されるようにしています。
- 呼び出し側では
render_field()
を使って簡潔に同じUIを作成できます。
これによって複数の入力フィールドを同じ見た目・同じ構造で記述することができ、コードの見通しがとても良くなります。
マクロ利用時の注意点とおすすめの使い方
マクロは便利ですが、使いすぎるとコードが分かりづらくなることもあります。
以下の点に注意しましょう。
- 適切な粒度で使う: 何でもかんでもマクロ化すると逆に読みにくくなることもあるため、「再利用性が高い部分」や「見た目が似ているUIパーツ」に絞って使うのがベストです。
- ネストを深くしすぎない: マクロの中でさらに他のマクロを呼び出すなどの構造にすると、保守が困難になることがあります。
- ファイル分割を活用: マクロは別ファイル(例:
_macro.html
)に定義し、必要に応じてfrom ... import ...
構文で呼び出すようにすると、テンプレート全体が整理されやすくなります。
まとめ|マクロでテンプレート開発を効率化しよう
今回はFlaskにおけるテンプレートマクロの基本について学びました。
- マクロとはテンプレート内で繰り返し使いたい構造を定義する仕組み
- 使い方を理解することで、テンプレートの記述を大幅に簡略化できる
テンプレートマクロを活用すれば、HTMLコードの再利用性が高まり、見通しも良くなります。
少し難しく感じるかもしれませんが、使い方に慣れればとても強力な武器になります。
自分だけの「便利テンプレート集」を作って、どんどん開発を効率化していきましょう!
練習問題:テンプレートマクロで再利用可能なボタンUIを作成しよう
この問題では、Jinja2テンプレートマクロを使って2種類のボタン(「送信」「キャンセル」)を表示するコードを作成します。
アプリファイルは下記の物を使用し、テンプレートファイル(HTMLファイル)を2つ作成してください。
この練習を通じて、マクロの定義方法やマクロを他のテンプレートで使う方法を学びましょう。
from flask import Flask, render_template app = Flask(__name__) @app.route("/") def index(): return render_template("index.html") if __name__ == "__main__": app.run(debug=True)
この問題の要件
以下の要件に従って「templates/_macro.html」を完成させてください。
show_button
という名前のマクロを定義すること- マクロの引数は
label
(ボタンに表示する文字列)とcolor
(ボタンの背景色に使うカラーコードまたは色名)とすること - マクロ内では以下の内容を持つボタンを表示すること:
style
属性で背景色をcolor
に設定し、文字色は白(white
)にすること- パディング(余白)を
10px
に設定すること - 枠線を非表示にし、角を5px丸くすること(
border-radius: 5px
)
以下の要件に従って「templates/index.html」を完成させてください。
_macro.html
に定義したマクロshow_button
をfrom "_macro.html" import show_button
構文で読み込むことh1
タグで「ようこそ!」、p
タグで「以下のボタンは、テンプレートマクロを使って表示しています。」という文を表示することshow_button
マクロを2回使用して、以下の2つのボタンを表示すること:
- ラベルが「送信」、色が
#007BFF
のボタン - ラベルが「キャンセル」、色が
#6C757D
のボタン
この問題を解くヒント
1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。
- ヒント:コードの構成を見る
-
正解のコードは上から順に以下のような構成となっています。
_macro.html(マクロ定義専用ファイル)
1:
_macro.html
というテンプレートファイルを作る(Flaskのtemplates/
フォルダの中)
2:ファイルの中で、show_button
という名前のマクロを定義する
3:マクロにはlabel
(ボタンの表示文字)とcolor
(背景色)という2つの引数を持たせる
4:<button>
タグを使ってボタンを作り、背景色をstyle
属性でcolor
に設定する
5:ボタンの文字としてlabel
を使うようにする
6:ボタンの文字色は白(white
)、角を丸くし、余白を入れるようにスタイルを整えるindex.html(メインテンプレート)
1:
index.html
というテンプレートファイルを作る(同じくtemplates/
フォルダ内)
2:HTML全体の構造を書く(<!DOCTYPE html>
〜<body>
まで)
3:ページに「ようこそ!」と「テンプレートマクロを使って表示しています」という見出し・説明を書く
4:from "_macro.html" import show_button
というコードでマクロを読み込む
5:show_button("送信", "#007BFF")
とshow_button("キャンセル", "#6C757D")
を使って2つのボタンを表示する
このヒントを見てもまだ回答を導き出すのが難しいと感じる場合は、先に正解のコードと解説を見て内容を理解するようにしましょう。
正解コード
例えば、以下のようなプログラムが考えられます。
- 正解コード
-
{# テンプレートマクロを定義するファイル #} {% macro show_button(label, color) %} {# ボタンを表示するマクロ。labelはボタンの文字列、colorは背景色に使うクラス名 #} <button style="background-color: {{ color }}; color: white; padding: 10px; border: none; border-radius: 5px;"> {{ label }} </button> {% endmacro %}
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>テンプレートマクロ練習</title> </head> <body> <h1>ようこそ!</h1> <p>以下のボタンは、テンプレートマクロを使って表示しています。</p> {# _macro.htmlの中のマクロを読み込む #} {% from "_macro.html" import show_button %} <div> {{ show_button("送信", "#007BFF") }} {# 青い「送信」ボタン #} </div> <div style="margin-top:10px;"> {{ show_button("キャンセル", "#6C757D") }} {# グレーの「キャンセル」ボタン #} </div> </body> </html>
正解コードの詳細解説
正解コードをブロックごとに分割して解説します。
- 正解コード(_macro.html)の詳細解説
-
マクロの定義
{% macro show_button(label, color) %}
macro
は、テンプレートの中で関数のように繰り返し使えるパーツ(マクロ)を定義する命令です。show_button
はマクロの名前で、テンプレート内で呼び出すとこの内容を出力できます。label
はボタンに表示するテキスト、color
はボタンの背景色として使う値です。label
やcolor
のような引数を設定することで、柔軟に使い回せるようになります。
ボタンの表示内容
<button style="background-color: {{ color }}; color: white; padding: 10px; border: none; border-radius: 5px;"> {{ label }} </button>
<button>
はHTMLでボタンを表示するタグです。style="..."
はCSSのスタイル指定で、ボタンの見た目を調整しています。{{ color }}
の部分で、マクロの引数color
の値を使って背景色を動的に変更しています。- 同様に
{{ label }}
でボタン内の文字を動的に表示しています。 - つまり、ボタンの見た目とラベルをマクロの引数で切り替えられる構成になっています。
マクロの終了
{% endmacro %}
macro
ブロックの終了を示すキーワードです。- Pythonでいう
def 関数名(): ...
の中にreturn
があるのと似ています。
- 正解コード(index.html)の詳細解説
-
HTMLの基本構成
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8"> <title>テンプレートマクロ練習</title> </head> <body>
- HTMLの基本的な構造を表しています。
<title>
タグでブラウザタブに表示されるタイトルを設定しています。- ページの本文(
<body>
)の中に実際の内容が書かれていきます。
見出しと説明
<h1>ようこそ!</h1> <p>以下のボタンは、テンプレートマクロを使って表示しています。</p>
<h1>
は大きな見出し、<p>
は段落(説明文)です。- ページの目的がわかりやすくなるように、タイトルと簡単な説明を書いています。
マクロの読み込み
_macro.html
に定義したマクロshow_button
をこのテンプレート内で使えるようにしています。from ファイル名 import マクロ名
という書き方で、外部テンプレートに定義されたマクロを取り込むことができます。
マクロの使用①
<div> {{ show_button("送信", "#007BFF") }} </div>
show_button
マクロを呼び出して、「送信」と書かれた青いボタンを表示しています。{{ ... }}
の中に書くことで、マクロの呼び出し結果がそのままHTMLとして表示されます。
マクロの使用②
<div style="margin-top:10px;"> {{ show_button("キャンセル", "#6C757D") }} </div>
- 今度は「キャンセル」と書かれたグレーのボタンを表示しています。
- 上のボタンと間隔を空けるために、
margin-top:10px
のスタイルがついています。
FAQ|テンプレートマクロの使い方と活用方法
- Q1. テンプレートマクロは別ファイルにまとめた方が良いですか?
-
はい。マクロの定義は
_macro.html
など別ファイルにまとめ、必要なテンプレートからfrom
構文で読み込むと、管理しやすくなります。
- Q2. マクロの引数に条件付きの値を渡すことはできますか?
-
可能です。マクロには任意の引数を渡すことができ、Jinja2内でif文などを使って条件分岐することもできます。
- Q3. テンプレートマクロは他のテンプレートと互換性がありますか?
-
基本的には同じJinja2テンプレートエンジンを使う限り、Flask以外でも同じ構文で利用できます。ただし、Flask特有のフィールド構造に依存する場合は注意が必要です。
質問用コンタクトフォーム
この記事を書くにあたりAIを活用しています。
人間の目による確認も行っていますが、もし間違い等ありましたらご指摘頂けると大変助かります。