flask的html模板的覆盖问题-创新互联

环境如下:
win10、Python3.6.5、Flask1.0.2

创新互联是一家集网站建设,中牟企业网站建设,中牟品牌网站建设,网站定制,中牟网站建设报价,网络营销,网络优化,中牟网站推广为一体的创新建站企业,帮助传统企业提升企业形象加强企业竞争力。可充分满足这一群体相比中小企业更为丰富、高端、多元的互联网需求。同时我们时刻保持专业、时尚、前沿,时刻以成就客户成长自我,坚持不断学习、思考、沉淀、净化自己,让我们为更多的企业打造出实用型网站。

项目结构如下:

/app
    /manage.py
    /main
        /views.py
        /templates
            index.html    
    /admin
        /views.py
        /templates 
            index.html  

/app/main/views.py内容如下:

from flask import Blueprint, render_template
main = Blueprint('main', __name__, template_folder='templates')
@main.route('/')
def index():
    return render_template('index.html')

/app/admin/views.py内容如下:

from flask import Blueprint, render_template
admin = Blueprint('admin', __name__, template_folder='templates', url_prefix='/admin')
@admin.route('/')
def index():
    return render_template('index.html')

/app/manage.py内容如下:

from flask import Flask
from app.main import main
from app.admin import admin

def create_app():
    app = Flask(__name__)
    app.register_blueprint(main)
    app.register_blueprint(admin)
    return app

在cmd中输入flask run(执行前记得设置FLASK_APP、FLASK_DEBUG)。待程序跑起来后,在浏览器
地址栏中输入127.0.0.1:5000,显示的是main蓝图的inde.html。输入127.0.0.1/admin/
显示的还是 main蓝图的index.html。奇怪,这是为什么呢?浮砂在网上搜索半天,最终在flask官方的
github上找到了相关issue,感兴趣的朋友可以看看。
Methodrender_templatedoes not use blueprint specifiedtemplate_folder#1361

此外,官方的文档中也有相关说明(Templates 部分):blueprint-resources
为了方便新手朋友,浮砂翻译成了中文,部分地方进行了补充。

Templates
模板

If you want the blueprint to expose templates you can do that by providing
thetemplate_folderparameter to the :class:Blueprintconstructor::

如果你想让蓝图暴露一些模板(比如flask-bootstrap扩展提供的"bootstrap/base.html"),
可以给在构造Blueprint时,指定template_folder参数。

admin = Blueprint('admin', __name__, template_folder='templates')

For static files, the path can be absolute or relative to the blueprint
resource folder.

对于静态的文件,路径可以是绝对或相对于蓝图资源文件夹的。

The template folder is added to the search path of templates but with a lower
priority than the actual application's template folder. That way you can
easily override templates that a blueprint provides in the actual application.
This also means that if you don't want a blueprint template to be accidentally
overridden, make sure that no other blueprint or actual application template
has the same relative path. When multiple blueprints provide the same relative
template path the first blueprint registered takes precedence over the others.

模板的全局搜索路径中会自动添加这个模板文件夹,并且它的优先级低于应用的模板文件夹。这样,
你可以在实际应用中,轻而易举地覆盖某个蓝图的模板。也就是说,如果不想让某个蓝图模板
莫名其妙地被覆盖,请确保其他的蓝图的模板相对路径不同于实际应用的模板相对路径。假如
多个蓝图模板被指定了相同的相对路径,那么,当flask搜索模板的时候,先被注册的蓝图模板
优先于后被注册的蓝图模板。

So if you have a blueprint in the folderyourapplication/adminand you
want to render the template'admin/index.html'and you have provided
templatesas atemplate_folderyou will have to create a file like
this: :file:yourapplication/admin/templates/admin/index.html. The reason
for the extraadminfolder is to avoid getting our template overridden
by a template namedindex.htmlin the actual application template
folder.

所以说,如果你在yourapplication/admin文件夹中编写了一个admin蓝图,而且你还想
渲染admin/index.html,并且你也给template_folder参数赋值了一个templates
那你就得像这样创建你的文件yourapplication/admin/templates/admin/index.html
额外的那个admin文件夹的存在,是为了不让实际应用的模板文件夹,把我们admin
蓝图的index.html文件覆盖掉。

To further reiterate this: if you have a blueprint namedadminand you
want to render a template called :file:index.htmlwhich is specific to this
blueprint, the best idea is to lay out your templates like this::

再说一遍,如果你有一个名为admin的蓝图,并且你想渲染这个蓝图中的一个名为
index.html的模板,最好的办法,就是把admin蓝图的模板路径弄成像这样:

yourpackage/
    blueprints/
        admin/
            templates/
                admin/
                    index.html
            __init__.py

And then when you want to render the template, use :file:admin/index.htmlas
the name to look up the template by. If you encounter problems loading
the correct templates enable theEXPLAIN_TEMPLATE_LOADINGconfig
variable which will instruct Flask to print out the steps it goes through
to locate templates on everyrender_templatecall.

此后,每当你想渲染admin蓝图的模板,只需在调用render_template函数时,把参数写成
admin/index.html就行了。假如你加载模板时遇到了问题,你可以把flask提供的一个名为
EXPLAIN_TEMPLATE_LOADING的配置项设置为可用。一旦启用了该配置,Flask就会在调用
render_template函数渲染模板时,把搜索模板的步骤全部输出出来,非常方便。

对于文章开头的例子,浮砂开启了flask的EXPLAIN_TEMPLATE_LOADING,再次访问
127.0.0.1:5000的时候,在cmd窗口中会有如下输出:

[2018-05-19 22:06:21,488] INFO in debughelpers: Locating template "index.html":
    1: trying loader of application "flask_server.app"
       class: jinja2.loaders.FileSystemLoader
       encoding: 'utf-8'
       followlinks: False
       searchpath:
         - D:\app\templates
       -> no match
    2: trying loader of blueprint "main" (flask_server.main)
       class: jinja2.loaders.FileSystemLoader
       encoding: 'utf-8'
       followlinks: False
       searchpath:
         - D:\app\main\templates
       -> found ('D:\\app\\main\\templates\\index.html')
    3: trying loader of blueprint "admin" (flask_server.admin)
       class: jinja2.loaders.FileSystemLoader
       encoding: 'utf-8'
       followlinks: False
       searchpath:
         - D:\app\admin\templates
       -> found ('D:\\app\\admin\\templates\\index.html')
Warning: multiple loaders returned a match for the template.
  The template was looked up from an endpoint that belongs to the blueprint "main".
  Maybe you did not place a template in the right folder?
  See http://flask.pocoo.org/docs/blueprints/#templates
127.0.0.1 - - [19/May/2018 22:06:21] "GET / HTTP/1.1" 200 -

根据官方给出的建议,浮砂尝试修改了项目的结构以及相关代码:

更改后的项目结构如下:
/app
    /manage.py
    /main
        /views.py
        /templates
            /main
                /index.html    
    /admin
        /views.py
        /templates
            /admin 
                index.html  

/app/main/views.py内容如下:

from flask import Blueprint, render_template
main = Blueprint('main', __name__, template_folder='templates')
@main.route('/')
def index():
    return render_template('main/index.html')  # 修改后

/app/admin/views.py内容如下:

from flask import Blueprint, render_template
admin = Blueprint('admin', __name__, template_folder='templates', url_prefix='/admin')
@admin.route('/')
def index():
    return render_template('admin/index.html')  # 修改后

再次执行flask run(执行前记得设置FLASK_APP、FLASK_DEBUG),访问127.0.0.1:5000
127.0.0.1:5000/admin,发现原来“被覆盖”的html页面已经能被正确地对应上了。

创新互联www.cdcxhl.cn,专业提供香港、美国云服务器,动态BGP最优骨干路由自动选择,持续稳定高效的网络助力业务部署。公司持有工信部办法的idc、isp许可证, 机房独有T级流量清洗系统配攻击溯源,准确进行流量调度,确保服务器高可用性。佳节活动现已开启,新人活动云服务器买多久送多久。


当前文章:flask的html模板的覆盖问题-创新互联
新闻来源:http://ybzwz.com/article/dcjiej.html