我是 Flask/Jinja2 的新手,所以也许我忽略了一些明显的事情,但是:
Flask 不应该开箱即用地允许蓝图中存在的模板吗?templates/
文件夹来扩展由我的应用程序定义的基本模板templates/
文件夹?即使蓝图还包含一个“默认”基本模板(我通过定义自己的同名基本模板来覆盖该模板),这难道不应该起作用吗?
答案是这另一个问题 https://stackoverflow.com/q/11233959/1337498让我认为这两件事绝对应该如此。具体来说,答案的一部分说:
如果有两个同名模板,[一个]在应用程序的模板文件夹中,[另一个在]蓝图的模板文件夹中,则应用程序的模板文件夹中的模板将优先。
但对我来说根本不是这样。事实上,它似乎有效opposite方式,即base.html
来自蓝图被我的应用程序中定义的页面拉入,即使我的应用程序定义了自己的base.html
(如果上述答案正确,则应该“优先”)。
在我的应用程序中我有:
myapp/
templates/
base.html
pages/
page_base.html
home_page.html
where pages/home_page
延伸pages/page_base
,这反过来又延伸base
.
我也在使用flask_user
来自 PyPI 的软件包,已安装(通过pip
) at /usr/local/lib/python2.7/dist-packages/flask_user/
。其templates文件夹排列如下:
flask_user/
templates/
base.html
flask_user/
[templates that extend base.html]
该包使其模板可供通过蓝图使用它的应用程序使用,该蓝图是通过以下调用在init_app
其功能UserManager
class (__init__.py,第 154 行 https://github.com/lingthio/Flask-User/blob/master/flask_user/__init__.py#L154):
# Add flask_user/templates directory using a Blueprint
blueprint = Blueprint('flask_user', 'flask_user', template_folder='templates')
app.register_blueprint(blueprint)
我最初的想法是通过定义我自己的myapp/templates/base.html
我可以自定义从模板呈现的页面flask_user/templates/flask_user/
看起来像我的应用程序中的其他页面,因为(根据引用的答案)我的base.html
应优先于flask_user
's base.html
.
但这是行不通的,更糟糕的是——更令人惊讶的是——my应用程序页面的默认外观为flask_user
的页面。
深层发掘...
研究 @Pralhad Narsinh Sonar 的建议,即模板搜索路径的排序可能存在问题,可能是由 的不确定性行为引起的DispatchingJinjaLoader._iter_loaders()
正如建议的Fewstreet.com 文章 http://fewstreet.com/2015/01/16/flask-blueprint-templates.html他引用说,我做了一个快速实验,看看是什么顺序_iter_loaders()
将为我的应用程序生成:
>>> from myapp.top import app, db
>>> from myapp.startup import init_app.init_app
>>> init_app(app, db)
>>> app.jinja_env.loader
<flask.templating.DispatchingJinjaLoader object at 0x7f233e396dd0>
>>> for loader in app.jinja_env.loader._iter_loaders('pages/home_page.html') :
... print loader, loader.searchpath
...
<jinja2.loaders.FileSystemLoader object at 0x7f233eb08490> ['/var/www/python/myapp/templates']
<jinja2.loaders.FileSystemLoader object at 0x7f233e36ef10> ['/usr/local/lib/python2.7/dist-packages/flask_user/templates']
正如预期的那样,迭代器为我的应用程序生成了加载程序templates/
folder first,在让出装载机之前flask_user/templates/
。事实上,_iter_loaders()
函数的结构经过精心设计,在返回之前返回应用程序的加载程序any蓝图的加载程序。 (如果我正确地阅读了 Fewstreet.com 的文章,那么它所关心的问题是multiple蓝图,因为我的应用程序只使用一个蓝图,这不是我当前的问题。)
这个结果让我更难理解为什么flask_user
's base.html
模板用于解析我的模板{% extends "base.html" %}
陈述*。既然我有自己的base.html
文件输入myapp/templates
,我认为模板系统没有任何理由查看中的任何内容flask_user/templates
渲染myapp/templates/pages/home_page.html
.
* For testing purposes I got rid of the indirection through pages/page_base.html
mentioned above.
So:显然还有其他问题,但是what?
我还没有充分了解相关代码flask/templating.py
or jinja2/loaders.py
了解为什么以及如何发生这种情况。这是我第一次尝试 Flask,我希望我不需要这么做。