PyTenjinを使ったサンプル
bonlifeです。id:yatt:20080127:1201410589 を見て、HTMLを出力するならテンプレートエンジン!ということで高速テンプレートエンジンと名高いTenjin(PyTenjin)を使ってみました。(string.Templateでも良さそうな気もしますが、なんとなく。) 調子に乗って、最後にはPyYAMLも使ってみましたよ。
- todo_tenjin_01.py
#! /usr/bin/env python # -*- coding: utf-8 -*- import tenjin from tenjin.helpers import * context = { "title":"todo", "todolists":[ {"todo": ["write program","submit bug report"]}, {"hobby":["bbb","plan RC"]}, {"else":["hogehoge"]}, ] } tmpl_filename = "todo.pyhtml" engine = tenjin.Engine() output = engine.render(tmpl_filename, context) print output
- todo.pyhtml
<html> <head> <title>${title}</title> </head> <body> <?py for genre in todolists: ?> <h2>${genre.keys()[0]}</h2> <ul> <?py for item in genre.values()[0]: ?> <li>${item}</li> <?py #end ?> </ul> <?py #end ?> </body> </html>
テンプレートが汚い。dict.keys()[0] とか dict.values()[0] がカコワルイ気がする…orz インデントをミスって何度かエラーになったのは秘密。
- 結果
<html> <head> <title>todo</title> </head> <body> <h2>todo</h2> <ul> <li>write program</li> <li>submit bug report</li> </ul> <h2>hobby</h2> <ul> <li>bbb</li> <li>plan RC</li> </ul> <h2>else</h2> <ul> <li>hogehoge</li> </ul> </body> </html>
想定通り。続いて、少しだけ修正。
- todo_tenjin_02.py
#! /usr/bin/env python # -*- coding: utf-8 -*- import tenjin from tenjin.helpers import * context = { "title":"todo", "todolists":[ {"todo": ["write program","submit bug report"]}, {"hobby":["bbb","plan RC"]}, {"else":["hogehoge"]}, ] } tmpl_filename = "todo.pyhtml" template = tenjin.Template(tmpl_filename) output = template.render(context) print output
01との違いは最後の方のみ。engine を生成するやり方から template を生成するやり方に変更。いくらかスッキリしたような、変わらないような。
続いて、Pythonスクリプトもテンプレートも両方とも変えてみる。
- todo_tenjin_03.py
#! /usr/bin/env python # -*- coding: utf-8 -*- import tenjin from tenjin.helpers import * context = { "title":"todo", "todolists":{ "todo": ["write program","submit bug report"], "hobby":["bbb","plan RC"], "else":["hogehoge"], } } tmpl_filename = "todo_03.pyhtml" template = tenjin.Template(tmpl_filename) output = template.render(context) print output
- todo_03.pyhtml
<html> <head> <title>${title}</title> </head> <body> <?py for key, value in todolists.iteritems(): ?> <h2>${key}</h2> <ul> <?py for item in value: ?> <li>${item}</li> <?py #end ?> </ul> <?py #end ?> </ul> </body> </html>
- 結果
<html> <head> <title>todo</title> </head> <body> <h2>hobby</h2> <ul> <li>bbb</li> <li>plan RC</li> </ul> <h2>todo</h2> <ul> <li>write program</li> <li>submit bug report</li> </ul> <h2>else</h2> <ul> <li>hogehoge</li> </ul> </ul> </body> </html>
todolistを辞書のリストからただの辞書に変更。(もはやtododict…。) テンプレートが結構スッキリ。ただ、出力順序が…orz そりゃあ、辞書だから順序は保証されないのは当然。
ということで、苦し紛れの数値PREFIX付き。
- todo_tenjin_04.py
#! /usr/bin/env python # -*- coding: utf-8 -*- import tenjin from tenjin.helpers import * context = { "title":"todo", "todolists":{ "01 todo": ["write program","submit bug report"], "02 hobby":["bbb","plan RC"], "03 else":["hogehoge"], } } tmpl_filename = "todo_04.pyhtml" template = tenjin.Template(tmpl_filename) output = template.render(context) print output
- todo_04.pyhtml
<html> <head> <title>${title}</title> </head> <body> <?py for key, value in sorted(todolists.iteritems()): ?> <h2>${key}</h2> <ul> <?py for item in value: ?> <li>${item}</li> <?py #end ?> </ul> <?py #end ?> </ul> </body> </html>
- 結果
<html> <head> <title>todo</title> </head> <body> <h2>01 todo</h2> <ul> <li>write program</li> <li>submit bug report</li> </ul> <h2>02 hobby</h2> <ul> <li>bbb</li> <li>plan RC</li> </ul> <h2>03 else</h2> <ul> <li>hogehoge</li> </ul> </ul> </body> </html>
うーん、無理無理感が強い…。強過ぐる。なんだかんだで02ぐらいが妥当かな。
最後に02をベースにデータも別ファイル(YAML)に分離。
- todo_tenjin_05.py
#! /usr/bin/env python # -*- coding: utf-8 -*- import tenjin from tenjin.helpers import * import yaml tmpl_filename = "todo.pyhtml" yaml_filename = "data.yaml" template = tenjin.Template(tmpl_filename) output = template.render(yaml.load(open(yaml_filename).read())) print output
- data.yaml
title: todo todolists: - todo: - write program - submit bug report - hobby: - make figure - plan RC - else: - hogehoge
YAMLではタブが使えないのに気付かず、イミフなエラーに悩まされたりしましたが、なかなかスッキリしてきたんじゃないかしら。"import pyyaml"とかしてミスってたのは過去の私。出力結果は、01や02と同じ。とりあえず、この中では 05 が一番カコ良さげ!たぶん、もっとスッキリしていてスマートなやり方があるはずなので、Pythonistaの皆さん、よろしくです。
ちなみに、PyTenjin はぱいぱいに上がってないので、SourceForgeから pyTenjin-0.6.1.tar.gz をダウンロード、展開、フォルダ移動して、"python setup.py install" ですよ。面倒! PyYAML は easy_install でインストールできますのでご安心あれ。