pyramidの1ファイルアプリケーションでテンプレートエンジンを利用する方法

# pyramidの1ファイルアプリケーションでテンプレートエンジンを利用する方法

pyramidでは[公式ドキュメントのhello worldの例](http://docs.pylonsproject.org/docs/pyramid/en/latest/narr/firstapp.html) の通りに、１ファイルからアプリケーションを作ることができる。
ただ、大抵の場合、プロジェクトを作成して(pcreate)、設定ファイルから起動(pserve development.ini)というパターンが多い。

一方でプロジェクトを作るのがめんどうだと感じるとき、１ファイルアプリケーションで済むのなら済ませたいという思いもある。
ところが、公式ドキュメントには1ファイルアプリケーションの例が少ない。
テンプレートエンジンを利用せずResponseオブジェクトを返す例で止まっていて、その先の記述が無い。

1ファイルアプリケーションでテンプレートエンジン(e.g. mako, jinja2, chameleon)を使う方法についてのメモ。

## hello world

公式ドキュメントから引用。[Creating Your First Pyramid Application — The Pyramid Web Framework v1.5.1](http://docs.pylonsproject.org/docs/pyramid/en/latest/narr/firstapp.html)

```py
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
from pyramid.response import Response


def hello_world(request):
    return Response('Hello %(name)s!' % request.matchdict)

if __name__ == '__main__':
    config = Configurator()
    config.add_route('hello', '/hello/{name}')
    config.add_view(hello_world, route_name='hello')
    app = config.make_wsgi_app()
    server = make_server('0.0.0.0', 8080, app)
    server.serve_forever()
```

以下の部分を変えたい。

- テンプレートエンジンではなく、Responseオブジェクトを返している
-- 例えば、makoを使いたい。
- html部分の変更を画面に変更するためには、アプリケーションを再起動する必要がある

## テンプレートエンジンの使い方

それぞれのテンプレートエンジン用のモジュールをincludeする

- pyramid_mako -- mako
- pyramid_jinaj2 -- jinja2
- pyramid_chameleon -- chameleon

makoの場合は、テンプレートのトップレベルのディレクトリの位置を指定する必要がある。

## 設定ファイルに書かれていた設定を1ファイルアプリケーションでも行う

プロジェクトを作った場合には設定ファイル(e.g. development.ini)にアプリケーションの設定を書く。
例えば先ほどのテンプレートエンジンの設定は以下の様に書かれる。

```
mako.directories = appname:templates
```

この"mako.directories"の設定を1ファイルアプリケーションでも行いたい。
そのような場合にはpyramid.config.Configuratorのコンストラクターに引数として辞書を渡す。

事実、プロジェクトを作った際のmain関数にはsettingsという引数が存在しこれがコンストラクタに渡されている。

```py
def main(global_config, **settings):
    """ This function returns a Pyramid WSGI application.
    """
    config = Configurator(settings=settings)
    config.include('pyramid_chameleon')
    config.add_static_view('static', 'static', cache_max_age=3600)
    config.add_route('home', '/')
    config.scan()
    return config.make_wsgi_app()
```

.iniファイルはぱーすされた後単なる辞書になるので辞書を渡してあげれば良い。
以下の様な形。

```py
if __name__ == '__main__':
    # アプリのソースコードと同一階層をtemplateのトップレベル階層にする
    here = os.path.abspath(os.path.dirname(__file__))
    settings = {"mako.directories": [here]}
    config = Configurator()
```

後は同様に以下のことを行いプロジェクトから作成した場合と同様にテンプレートエンジンを使った１ファイルアプリケーションが作れる。
(そもそもテンプレート部分を分割しているため1ファイルアプリケーションとは呼べないかもしれない)

- view_configの変わりにadd_viewで登録
- add_mako_rendererで".html"で終わるファイルをmako テンプレートとして扱う

これらを合わせた例は以下のとおり。

onefile.py

```py
from wsgiref.simple_server import make_server
from pyramid.config import Configurator
import os.path


def hello_world(request):
    return {"name": request.matchdict["name"]}


if __name__ == '__main__':
    here = os.path.dirname(os.path.abspath(__file__))
    settings = {"mako.directories": here,
                "pyramid.reload_all": True}
    config = Configurator(settings=settings)

    config.include("pyramid_mako")
    config.add_mako_renderer(".html")

    config.add_route('hello', '/hello/{name}')
    config.add_view(hello_world, route_name='hello', renderer="hello.html")

    app = config.make_wsgi_app()
    server = make_server('0.0.0.0', 8080, app)
    server.serve_forever()
```

hello.html

```html
Hello ${name}!
```

以下に関しては"pyramid.reload_templates"をTrueに設定すれば良い。

- html部分の変更を画面に変更するためには、アプリケーションを再起動する必要がある