Flask:Blueprint中的模板继承自App中的模板?

2024-04-24 23:09:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我是一个十足的Flask/Jinja2新手,所以也许我忽略了一些显而易见的东西,但是:

Flask不应该开箱即用,允许blueprint的templates/文件夹中的模板扩展由我的应用程序的templates/文件夹定义的基本模板吗?即使蓝图还包含一个“默认”的基本模板,我通过定义自己的同名基础模板来覆盖它,这难道不起作用吗?在

this other SO question的回答让我认为这两件事绝对应该是这样。特别是答案中说:

If there are two templates with same name[, one] in app's templates folder and [the other in] blueprint's template folder, then template in app's templates folder will get priority.

但这对我来说根本不起作用。事实上,它的工作方式似乎与相反,也就是说,蓝图中的base.html被我的应用程序中定义的页面拖入,即使我的应用程序定义了自己的base.html(如果上面的答案是正确的,它应该“获得优先权”)。在

在我的应用程序中,我有:

myapp/
   templates/
       base.html
       pages/
           page_base.html
           home_page.html

其中pages/home_page扩展{},后者反过来扩展{}。在

我还使用PyPI中的flask_user包,它是由pip安装在/usr/local/lib/python2.7/dist-packages/flask_user/上的。其模板文件夹的排列如下:

^{pr2}$

此包通过蓝图使使用它的应用程序可以使用它的模板,它在其UserManager类(^{}, line 154)的init_app函数中建立了一个蓝图:

    # 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_userbase.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()函数是经过精心设计的,在返回任何蓝图加载程序之前返回应用程序的加载程序。(如果我在读fewstreet.com网站文章正确,它关注的问题是多个蓝图之间的不确定性排序,因为我的应用程序只使用一个蓝图,这不是我当前的问题。)

这个结果使我更难理解为什么使用flask_userbase.html模板来解析我的模板的{% extends "base.html" %}语句*。鉴于我在myapp/templates中有自己的base.html文件,我认为模板系统没有理由查看flask_user/templates中的任何内容来呈现{}。在

*出于测试目的,我去掉了上面提到的pages/page_base.html的间接寻址。

很明显,有些事情出了问题,但是什么事?在

我还没有在flask/templating.pyjinja2/loaders.py中搜索足够的相关代码来理解为什么会发生这种情况以及如何发生。这是我第一次进入烧瓶,我希望我不需要。在


Tags: 文件夹模板app应用程序flaskbase定义html
2条回答

答案是:

一直以来,我都在用debug=True运行(并重新加载)我的应用程序。在

这对于自动重新加载已更改的Python模块非常有用。在

但是对于改变了的模板?嗯。。。没那么多。在

在我的home_page.html模板中引入了一个断点,并使用Flask调试器回顾了几个堆栈帧之后,我发现Jinja2使用LRU缓存来存储(按名称)它已经解析的模板。在

因为在已经加载了一个flask_user页面(login.html)之后,我萌生了创建自己的base.html模板的想法,而当我引入myapp/templates/base.html时,缓存中已经有了一个名为base.html的模板。在

因此,我停止并重新启动了应用程序,现在我的home_page.html和{}的{}都正确地继承了mybase.html,而不是{}base.html。我怀疑在我重启应用程序之前,我自己的base.html从未被我的应用程序的模板加载器读取过。在

这是一个相当重要的问题,我相信,对于新手来说,这是一个需要解决的问题。我就把这个留在这里,希望有一天它能帮助那些碰巧踏入这个陷阱的人。在

如果您可以共享代码的blueprint部分,将非常有帮助。

这可能是由于搜索路径中出现故障导致的——它将第一行模板视为要显示的模板。为了避免这种情况,您可以始终唯一地重命名模板文件。如果出于任何限制或偏好,如果您想保持相同的名称,那么您可以尝试将模板文件保存在主模板文件夹的子目录下。在

你可以通过这个链接-http://flask.pocoo.org/docs/0.10/blueprints/

选项1

请尝试使用此文件夹结构-您还需要在blueprints-

myapp/
  templates/
    base.html
    pages/
      page_base.html
      home_page.html
  flask_user/
    pages/
      flask_user
        page_base.html
        home_page.html

关于这个问题{/strong}

选项2

^{pr2}$

在上面的结构中,每个模块都有自己的路由文件,即-view.py,因此单独的blueprint配置以使每个功能模块化。在

请看一下https://www.digitalocean.com/community/tutorials/how-to-structure-large-flask-applications

相关问题 更多 >