Flask には Blueprintというアプリケーションをモジュール化出来る機能が備わっていますが、このBlueprintのtemplate_folderパス解決にはちょっとした罠があります。
Flaskで以下のようなパッケージ構成を組んだと仮定します。
run.py admin/ __init__.py views.py pages/ index.html frontend/ __init__.py views.py pages/ index.html
admin/views.py
from flask import Blueprint, render_template admin = Blueprint('admin', __name__, template_folder='pages') @admin.route('/') def index(): return render_template('index.html')
frontend/views.py
from flask import Blueprint, render_template frontend = Blueprint('frontend', __name__, template_folder='pages') @frontend.route('/') def index(): return render_template('index.html')
run.py
app = Flask(__name__) from admin.views import admin app.register_blueprint(admin) from frontend.views import frontend app.register_blueprint(frontend)
一見template folder
として admin/views.py
では admin/pages/
を 、
frontend/views.py
ではfrontend/pages/
を参照するように読めます。
しかしこのコードは正常に動作しません。
admin/views.py
と frontend/views.py
で template_folder
が、admin/pages/
になるか 、 frontend/pages/
になるかは不定となります。
Flask Blueprintのマニュアルを参照してみると以下のように記述があります。 http://flask.pocoo.org/docs/0.10/blueprints/
So if you have a blueprint in the folder yourapplication/admin and you want to render the template 'admin/index.html' and you have provided templates as a template_folder you will have to create a file like this: yourapplication/admin/templates/admin/index.html.
つまり、以下のようなパッケージ構成にする必要があるということです。
run.py admin/ __init__.py views.py pages/ admin/ index.html frontend/ __init__.py views.py pages/ frontend/ index.html
admin/views.py
from flask import Blueprint, render_template admin = Blueprint('admin', __name__, template_folder='pages') @admin.route('/') def index(): return render_template('admin/index.html')
frontend/views.py
from flask import Blueprint, render_template frontend = Blueprint('frontend', __name__, template_folder='pages') @frontend.route('/') def index(): return render_template('frontend/index.html')
この仕様は度々Flaskの利用者に誤解を与えてきたようで、以下のように Issueでも議論にもなりました。 Blueprint template lookup not documented enough · Issue #266 · pallets/flask · GitHub
なぜこのような仕様になっているかというと、実装上の都合です。
Flaskで指定するtemplate_folderは Jinja2 の FileSystemLoader のsearchpathに渡されます。
searchpathはアプリケーションのトップレベルに追加され、再帰的に検索されるため、template_folderで指定したディレクトリ文字列がかぶっているとどのテンプレートを選択すれば良いのか一意に特定出来ません。
そのため、このような仕様になっています。
Flask Web Development: Developing Web Applications with Python | |
Miguel Grinberg O'Reilly Media 2014-04-28 売り上げランキング : Amazonで詳しく見る by G-Tools |
Pythonスタートブック | |
辻 真吾 技術評論社 2010-04-24 売り上げランキング : 1920 Amazonで詳しく見る by G-Tools |