PythonのテンプレートエンジンMakoで日本語を使う方法まとめ。
テスト環境: Python 2.5, Mako-0.3.2
Makoの内部処理はunicodeで行われる。そのため入出力時にエンコーディング指定を正しく行い、テンプレート変数の展開時にunicodeオブジェクトに変換することが必要になる。
入力時
テンプレートファイルが読み込まれる際に、ファイルで使用されている特定のエンコーディング・スキーム(utf-8など)に基づいて、unicode オブジェクトへのデコードが行われる。
最も優先順位の高い指定は、テンプレートファイル先頭行の magic encoding comment である。この一行はテンプレートの内容に含まれないので、HTMLなどに書いても問題ない。
## -*- coding: utf-8 -*-
<p>まこまこ</p>
次に優先されるのは Template コンストラクタにおける input_encoding の指定である。
from mako.template import Template
tmpl = Template(filename="view.html", input_encoding="utf-8")
そして最も優先順位が低く、広範囲に適用されるのが TemplateLookup のコンストラクタにおける input_encoding の指定である。実際のアプリケーションで最も良く使われるのがこれだと思われる。
from mako.lookup import TemplateLookup
lookup = TemplateLookup(directories=["views/"], input_encoding='utf-8')
tmpl = lookup.get_template("index.html")
出力時
render メソッドを使ってレンダリング結果を取り出す際に、Mako内部の unicode オブジェクトが str オブジェクトにエンコードされる。このとき使用されるエンコーディングは Template または TemplateLookup の output_encoding で指定できる。
## coding: utf-8
from mako.template import Template
tmpl = Template(u"まこまこ", input_encoding="utf-8", output_encoding="utf-8")
out = tmpl.render()
print len(out) # => 12
print type(out) # => <type 'str'>
しかし render_unicode メソッドを使えば unicode オブジェクトをそのまま取り出すことができる。出力先が unicode に対応しているのなら、これをそのまま使うのが最もトラブルが少ないと思う。
tmpl = Template(u"まこまこ", input_encoding="utf-8")
out = tmpl.render_unicode()
print len(out) # => 4
print type(out) # => <type 'unicode'>
もちろん必要なら取り出したunicodeオブジェクトの encode メソッドを使うこともできる。
tmpl = Template(u"まこまこ", input_encoding="utf-8")
out = tmpl.render_unicode().encode('euc-jp')
print len(out) # => 8
print type(out) # => <type 'str'>
式展開
テンプレート内の式は自動的に unicode オブジェクトに変換されるため、非ASCII文字を含む可能性のある str オブジェクトを使用する場合は、手動で適切なエンコーディングを指定してデコードしなければならない。
<p>${strobj.decode('utf-8')}</p>
まとめ
- TemplateLookup の input_encoding で最も一般的なエンコーディングを指定しておく。必要に応じて Template の input_encoding や magic coding comment を使用する。
- 可能な限り render_unicode を使用する。
- 非ASCII文字を含む可能性のある str オブジェクトをテンプレート内で使用する場合は、手動でデコードする。
参照