⛩️

Jinjaテンプレートから自作関数を呼び出す

2023/08/02に公開

ご閲覧ありがとうございます。
FlaskのJinjaテンプレートでFlask側で定義した自作関数を呼び出したいと思ったのですが、少し面倒だったので記録として残しておきます。

検証環境

環境 バージョン
OS MacOS 12.3
Python 3.9.6
Flask 2.0.2
Jinja 3.1.1

解決したい問題

例えば、Flaskで動的に画面に値を表示したい時、Jinjaにはそのような関数は用意されていないため、一般的にはテンプレート呼び出し時に結果を引き渡す必要があります

コード例

app.py
from flask import Flask, render_template

app = Flask(__name__)

def get_host_name():
	return "Zennnnnn"

@app.route("/")
def root():
	return render_template("root.html", host_name = get_host_name())
root.html
<html>
	<body>
		<div>ホスト名: {{ host_name }}</div>
		<!-- ホスト名: Zennnnnn-->
	</body>
</html>

上記は渡す値が1つだったのでまだマシですが、これが複数に渡ると管理が困難になります
下記のように多くのパラメータをとる画面をバリデーションに引っかかった等の理由で画面を戻す場合、パラメータをそれぞれ設定し直す必要があるためとても大変です
私はこれが原因で何度もエラーを出してます...

app.py
@app.route("foo")
def many_params():
	return render_template("many_params.html",
                               param1 = "...",
                               param2 = "...",
                               param3 = "...",
                               param4 = "...",
                               param5 = "...",
                               and_more = "..."
                          )

実装

パラメータ設定が大変なのであればテンプレートで設定すればいいじゃんという発想の元です
Flaskインスタンス生成時にjinja_envというパラメータが設定されるので利用します

実装例

app.py
def get_host_name():
	return "Zennnnnn"

app = Flask(__name__)

# jinja_env.globalsに名前と関数をセット
app.jinja_env.globals["get_host_name"] = get_host_name

@app.route("/")
def root():
	return render_template("root.html")
root.html
<div>ホスト名: {{ get_host_name() }}</div>

下記URL先の既存関数と同じ名前で定義すると上書きされるっぽいので注意が必要です
テンプレート#標準のコンテキスト - Flask

まとめ

2023年現在で新しくFlaskプロジェクトを始める人はいるのか疑問ですが、Flaskを使っている人は使ってみてください
今回の方法を用いれば、多数のViewで使う処理を共有できるようになります
しかし、Viewにビジネスロジックが漏れる可能性があるため使用には注意が必要です
(前職のプロジェクトではViewに漏れ出して管理が大変でした...)
用法要領を守って楽しくコーディングしましょう!

拙文最後までお読みいただきありがとうございます。
気軽にTwitterフォロー、いいね!をお願いします。

参考

FlaskのJinja2テンプレでpython内の変数をどこでも使ってみる - Qiita

Discussion