【Python】FlaskのJinja2と別でimportしたJinja2を使って文字の置換を二回行う
こんばんは、葛の葉です。
Flaskの文字置換を二段階にわけて行いたい場合の方法を書きます。
環境
python 3.6.5
flask 1.0.2
jinja2 2.10
やり方の説明
元のhtml -> custom_jinja -> flaskのjinja2 できれいにする。
custom_jinjaでは::で挟んだ変数を読み込む
flaskのjinja2では{{}}で挟んだ変数を読み込む
jinja2とjinja2.Environmentを使う
flask内のjinja2とは別のjinja2を使用する。
その別のjinja2を便宜的にカスタムjinjaと呼ぶことにする。
jinja2.Environment()内の引数にある以下の値を変更、それをカスタムjinjaというインスタンスとして扱う。
variable_start_stringは変数を囲う最初の文字
variable_end_stringは変数を囲う最後の文字
custom_jinja = jinja2.Environment(
loader=jinja2.FileSystemLoader('templates'),
variable_start_string=':',
variable_end_string=':'
)
説明が前後したけど、loader=jinja2.FileSystemLoader('templates')はtemplateファイルを読み込むディレクトリ名をtemplatesにしています。
page = custom_jinja.get_template('index.html')
と、このようにすることで、templateファイルを読み込めます。
render_template = pages.render(variable_name='value')
と、することでvariable_nameの変数をtemplateファイルに送ることができます。
こんな感じ
sandbox_flask.py
templates/
├index.html
└layout.html
sandbox_flask.py
from flask import Flask, render_template, render_template_string
import jinja2
app = Flask(__name__)
custom_jinja = jinja2.Environment(
# 元htmlの保存されているディレクトリ名。flaskと併用するので以下の値。
loader=jinja2.FileSystemLoader('templates'),
#デフォルトでは{%にあたるもの。flaskのjinjaと重複しない値にする。
block_start_string='[{[{[Q',
#デフォルトでは%}にあたるもの。flaskのjinjaと重複しない値にする。
block_end_string='Q]}]}]',
# このvariable...と続くステータスを挟みたい文字にする。
variable_start_string=':',
variable_end_string=':',
# オートエスケープは特殊文字等をエスケープします。
autoescape=False)
# 定数のようなもの。:Key: -> Value にしてくれる。
SPECIAL_CONVERSION_CHARACTER = {
'test': '!TesT!'
}
# SPECIAL_CONVERSION_CHARACTERが不要ならここの処理も不要
custom_jinja.globals.update(SPECIAL_CONVERSION_CHARACTER)
@app.route("/")
def hello():
# index.htmlを元にhtmlを生成します。
page = custom_jinja.get_template('index.html')
template = page.render(name='サンプルタイガー')
return render_template_string(template, name='サンプルドラゴン', title='Titleだよ!!!')
if __name__ == "__main__":
app.run(debug=True)
layout.html
<!doctype html>
<html>
<head>
<meta http-equiv="content-type" charset="utf-8">
<title>{{ title }}</title>
</head>
<body>
{% block content %}
{% endblock %}
</body>
<footer>
</footer>
</html>
index.html
{% extends "layout.html" %}
{% block content %}
<p>
:':name:':=:name:<br>
{{ '{{ name }}' }}={{ name }}<br>
</p>
:test:
{% endblock %}
表示はこんな感じ
:name:=サンプルタイガー
{{ name }}=サンプルドラゴン
!TesT!

STR型を変換する
bunsho = ':one:である :two:なのだ'
以下のような辞書を参照してAである Bなのだという文字列にしたい場合
{'one': 'A','two': 'B'}
importやcustom.jinjaなどの記載省略
...
@app.route("/")
def hello():
...省略...
@app.route("/x")
def xstring():
string = custom_jinja.from_string(':one:である :two:なのだ ')
strings = string.render(
{
'one': 'A',
'two': 'B'
}
)
return render_template('strings.html', strings=strings)
...
strings.html ( {{ strings }}と書かれているだけのhtml)
{{ strings }}
出力するとこうなる
Aである Bなのだ
出来なかった個所
key名が数字のみ場合は参照されない。
string = custom_jinja.from_string(':1:である :2:なのだ ')
strings = string.render(
{
'1': 'A',
'2': 'B'
}
)
return render_template('strings.html', strings=strings)
-> 1である 2なのだ