Displaying posts written in

4月 2010

テンプレートエンジンMakoで日本語を使う

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 オブジェクトをテンプレート内で使用する場合は、手動でデコードする。

参照