Hep*_*tus 5 python templates jinja2 flask
我是一个完全的 Flask/Jinja2 新手,所以也许我忽略了一些明显的东西,但是:
开箱即用的 Flask 是否应该允许存在于蓝图templates/文件夹中的模板扩展由我的应用程序templates/文件夹定义的基本模板?即使蓝图还包含一个“默认”基本模板,我通过定义自己的同名基本模板来覆盖它,这不应该工作吗?
另一个 SO 问题的答案让我认为这两件事绝对应该如此。特别是答案的一部分:
如果应用程序的模板文件夹中有两个同名的模板[,一个] 和蓝图的模板文件夹中的[另一个],则应用程序模板文件夹中的模板将获得优先权。
但这对我来说根本不起作用。事实上,它似乎工作的相反的方式,即base.html从蓝图正由我的应用程序定义的页面拉,即使我的应用程序定义了自己的base.html(这应该“得到优先权”如果以上的答案是正确的)。
在我的应用程序中,我有:
myapp/
templates/
base.html
pages/
page_base.html
home_page.html
Run Code Online (Sandbox Code Playgroud)
其中pages/home_pageextends pages/page_base,反过来extends base。
我也在使用flask_user来自 PyPI的包,它是安装pip在/usr/local/lib/python2.7/dist-packages/flask_user/. 其模板文件夹排列如下:
flask_user/
templates/
base.html
flask_user/
[templates that extend base.html]
Run Code Online (Sandbox Code Playgroud)
该包通过在init_app其UserManager类的函数(__init__.py第 154 行)中通过以下调用建立的蓝图将其模板提供给使用它的应用程序:
# Add flask_user/templates directory using a Blueprint
blueprint = Blueprint('flask_user', 'flask_user', template_folder='templates')
app.register_blueprint(blueprint)
Run Code Online (Sandbox Code Playgroud)
我最初的想法是,通过定义我自己的页面,我myapp/templates/base.html可以自定义从模板呈现的页面,使其flask_user/templates/flask_user/看起来像我的应用程序中的其他页面,因为(根据引用的答案)我base.html应该优先于flask_user's base.html。
但这不起作用,更糟糕的是 - 更令人惊讶的是 -我的应用程序页面被赋予了页面的默认外观flask_user。
深层发掘...
查看@Pralhad Narsinh Sonar 的建议,即模板搜索路径的排序可能存在问题,这可能是由他引用DispatchingJinjaLoader._iter_loaders()的somestreet.com 文章中建议的非确定性行为引起的,我做了一个快速实验,看看是什么排序_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']
Run Code Online (Sandbox Code Playgroud)
正如预期的那样,迭代器得到我的应用程序的加载程序templates/文件夹第一,产生了装载机前flask_user/templates/。事实上,该_iter_loaders()函数经过精心设计,在返回任何蓝图的加载器之前返回应用程序的加载器。(如果我正确阅读了 somestreet.com 文章,那么它所关注的问题是多个蓝图之间的非确定性排序,因为我的应用程序只使用一个蓝图,这不是我当前的问题。)
这个结果让我更难理解为什么使用flask_user的base.html模板来解析模板的{% extends "base.html" %}语句*。鉴于我有自己的base.html文件myapp/templates,我认为模板系统没有任何理由查看flask_user/templates要呈现的任何内容myapp/templates/pages/home_page.html。
*出于测试目的,我通过pages/page_base.html上面提到的方式摆脱了间接。
所以:显然其他地方出了问题,但是什么?
我还没有了解足够的相关代码,flask/templating.py也jinja2/loaders.py没有了解这可能发生的原因和方式。这是我第一次涉足 Flask,我希望我不需要这样做。
答案是:
一直以来,我一直在运行(并重新加载)我的应用程序debug=True。
这对于自动重新加载更改的 Python 模块非常有用。
但是对于改变的模板呢?嗯……没那么多。
在我的模板中引入断点home_page.html并使用 Flask 调试器回顾几个堆栈帧后,我发现 Jinja2 使用 LRU 缓存来存储(按名称)它已经解析的模板。
因为我在已经加载了一个page( )之后base.html就萌生了创建自己的模板的想法,该页面最初是继承自 的,所以在我引入时,缓存中已经有一个命名的模板了。flask_userlogin.htmlflask_user/templates/base.htmlbase.htmlmyapp/templates/base.html
所以我停止并重新启动了应用程序,现在 myhome_page.html和flask_user's都正确地从my而不是从'slogin.html继承。我怀疑在我重新启动应用程序之前,我自己的应用程序的模板加载器从未读取过我自己的应用程序。 base.htmlflask_userbase.htmlbase.html
对于新手来说,这是一个相当重要的——而且,我相信,没有记录的——必须弄清楚的问题。我将其留在这里,希望有一天它能帮助其他碰巧踏入这个特定陷阱的人。
| 归档时间: |
|
| 查看次数: |
2710 次 |
| 最近记录: |