【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なのだ