DBに格納したmakoテンプレートをレンダリングする

Pylons において、DBに格納したMakoテンプレートをレンダリングするために調べたことを公開します。

Buffet

Pylons は、pylons.templating:Buffet を介してテンプレートをレンダリングしています。こんな感じ。

        render()          render()
Pylons  --------> Buffet ----------> Mako 

こうすることで、Buffetの仕様にのっとったインタフェースさえ用意すれば、そのテンプレートをPylonsから利用することができます。Buffet によって、テンプレートの持つ最低限の機能を抽象化しているわけです。

Buffet にインタフェースとなるクラスを教える仕組み

Buffet が、どのテンプレートのどのクラスを実体化して、render() を呼ぶべきかは entry_points に書かれています。

Mako の場合

      [python.templating.engines]
      mako = mako.ext.turbogears:TGPlugin

Myghty の場合(Pylons が提供しています。Pylons の entry_points 参照)

      [python.templating.engines]
      pylonsmyghty = pylons.templating:MyghtyTemplatePlugin [myghty]

Buffet は python.templating.engines の entry_point を探して、使えるテンプレートの一覧を取得するわけです。
このあたりの話は、pylons.templating のソースを読むと勉強になります。

DBに格納したMakoテンプレートをレンダリングする

Pylons のテンプレートレンダリングは Buffet を使って行われるため、DBに格納したmakoテンプレートのレンダリングにおいても、同様のアプローチをとろうと思いました。しかし、Buffet はあくまで ファイルベースのテンプレートを前提としていて、文字列を入力としたテンプレートレンダリングが弱いです。

これに悩んで、pylons-discuss に相談したところ、Mike Orr から適格な返事がきました。

There's no reason you have to use Buffet. Its purpose is to hide the
differences between template engines for simple cases. But if you
want to use extra features of a particular engine, you can just use
the engine in its native manner, or write your own render function.

ごもっとも。
今回の場合、DBに格納しているのは"Mako"のテンプレートと決まっています。
Buffet に渡しているMako のオプションも、自分で指定したもの。pylons.config やenviron にちゃんと入っています。

というわけで、Buffet を使うのをやめて、直接 Mako をたたくカスタムな render() メソッドを追加することにしました。

追伸

pylonshq がロゴの話で盛り上がっています。

posted by id:junya_hayashi