Flaskでテンプレートディレクトリを指定する

動機

PythonにはFlaskというRubyでいうsinatraライクなマイクロフレームワークがあり、こいつのテンプレートエンジンにはJinja2というPHPでいうSmartyライクなテンプレートエンジンが使われている。
で、Flaskでユニットテストを書いていた時に本番環境とテスト用のディレクトリ分けたいと思った。
というのはディレクトリ構造同じにしておいて期待通りのテンプレートがちゃんとレンダリングされてればいいかぐらいのノリだったため。

Jinja2から直接テンプレートディレクトリを指定する

ググってもやはり日本語情報は引っかからなかったのと公式ドキュメントとりあえず10分ほど探してみても見つからないということで、とりあえずついったーに投げたら反応あるかもという他力本願全開で投げたらid:shimizukawaさんからレスを頂いた(id:shimizukawaさん情報ありがとうございました!)
id:shimizukawaさんから頂いた案としては以下。

from jinja2 import Environment, FileSystemLoader
env = Environment(loader=FileSystemLoader('templates'))
template = env.get_template('index.html')
template.render()

ただid:shimizukawaさんもFlask側から設定する方法は分からない、分かったら教えてほしいということだったのでこの情報を基に調べてみることに。

Flask側からテンプレートディレクトリを指定する

調べるやいなや公式ドキュメントのAPIの章に思いっきり書いてあった・・・
使い方はflaskインスタンスのjinja_loader属性にFileSystemLoader('hoge_dir')みたいな感じで割り当ててやればよい。
例は以下。

2010/11/9 修正

id:shimizukawaさんから

app = FileSystemLoader('hoge_dir')

だとappを上書きしていると指摘を受けたので修正しました。

app.jinja_loader = FileSystemLoader('hoge_dir')

ここでのappという変数はflaskインスタンスチュートリアルのコードと同じ)
そしてview関数の方は元々あるFlask.render_template()関数を呼び出す

@app.route("/")
def index():
    from flask import render_template
    return render_template('index.html')

もうちょっと全体が見えるように書いたのが以下。

from flask import Flask
from jinja2 import FileSystemLoader

app = Flask(__name__)
app.jinja_loader = FileSystemLoader('hoge_dir')

@app.route("/")
def index():
    from flask import render_template
    return render_template('index.html')

これで割とすっきりしたかなと思う。
ただ、テスト時にはテンプレートのディレクトリは変えてやらないといけない事にご注意を。

でもまあloaderの存在は知らなかったので教えてもらわなかったら未だにドキュメントと格闘していたかもしれない。

全体のソースコード

コード片じゃ分かりにくと思うのでサンプルコードをユニットテスト付きでZIP公開。
http://d.hatena.ne.jp/aroma_black/files/yourapplication.zip?d=download

不満点

flask.config.form_object()メソッドみたいにさくっと出来たらいいなと思った。
そうすれば設定ファイルが全部外だし出来るし。
これはそのうち・・・