【发布时间】:2015-09-06 14:46:50
【问题描述】:
我完全是 Flask/Jinja2 新手,所以也许我忽略了一些明显的东西,但是:
开箱即用的 Flask 是否应该允许存在于蓝图的 templates/ 文件夹中的模板扩展由我的应用程序的 templates/ 文件夹定义的基本模板?即使蓝图还包含一个“默认”基本模板(我通过定义我自己的同名基本模板来覆盖它),这难道不应该工作吗?
this other SO question 的答案让我觉得这两件事绝对应该如此。特别是答案的一部分:
如果有两个同名的模板[,一个]在app的templates文件夹和[另一个在]blueprint的template文件夹,那么app的templates文件夹中的模板优先。
但这对我来说根本不是这样。事实上,它似乎以 相反 的方式工作,即 blueprint 中的 base.html 被我的应用程序中定义的页面拉入,即使我的应用程序定义它自己的base.html(如果上述答案正确,它应该“优先”)。
在我的应用中,我有:
myapp/
templates/
base.html
pages/
page_base.html
home_page.html
其中pages/home_page 扩展pages/page_base,而后者又扩展base。
我还使用了 PyPI 中的 flask_user 包,它安装在(pip)/usr/local/lib/python2.7/dist-packages/flask_user/。其模板文件夹排列如下:
flask_user/
templates/
base.html
flask_user/
[templates that extend base.html]
此包通过其init_app 类的init_app 函数(__init__.py, line 154) 中的以下调用建立的蓝图将其模板提供给使用它的应用程序:
# 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 的base.html。
但这不起作用,更糟糕的是——更令人惊讶的是——我的应用程序的页面被赋予了flask_user页面的默认外观。
深入挖掘...
查看@Pralhad Narsinh Sonar 的建议,即模板搜索路径的排序可能存在问题,这可能是由DispatchingJinjaLoader._iter_loaders() 的非确定性行为引起的,正如他引用的fewstreet.com article 中所建议的那样,我做了一个快速实验看看 _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/ 文件夹生成加载器,然后再为flask_user/templates/ 生成加载器。事实上,_iter_loaders() 函数经过精心设计,在返回任何蓝图的加载程序之前返回应用程序的加载程序。 (如果我正确阅读了几个这不是我当前的问题。)
这个结果让我更难理解为什么flask_user 的base.html 模板被用来解析我的模板的{% extends "base.html" %} 语句*。鉴于我在myapp/templates 中有自己的base.html 文件,我认为模板系统没有任何理由查看flask_user/templates 中的任何内容来呈现myapp/templates/pages/home_page.html。
* 出于测试目的,我摆脱了上面提到的通过pages/page_base.html 的间接寻址。
所以: 显然还有其他问题,但是什么?
我还没有深入了解flask/templating.py 或jinja2/loaders.py 中的相关代码,无法理解为什么以及如何发生这种情况。这是我第一次尝试 Flask,我希望我不需要这样做。
【问题讨论】:
标签: python templates flask jinja2