资讯专栏INFORMATION COLUMN

使用 Blueprint 要注意 render_template 函数

stonezhu / 2583人阅读

摘要:此文章主要是为了记录在使用的过程中遇到的问题。本章主要讨论函数的问题。而对于不同里的,是依靠所注册的蓝图以及不同的前缀来进行区分。写项目的时候,要注意此坑,函数里所调用的模板一定要保证命名在整个项目中的唯一性。

此文章主要是为了记录在使用 Flask 的过程中遇到的问题。本章主要讨论 render_template 函数的问题。

使用 Flask 的同学都应该知道,项目中的 url 和视图函数是在字典里一一对应着的,再详细一点,就是 url 对应着 endpoint,视图函数也对应着 endpoint,并且 endpoint 在字典里是唯一存在的。

而对于不同 Blueprint 里的 url,是依靠所注册的蓝图以及不同的前缀来进行区分。但是在视图函数中所调用的 render_template 函数可得不到 endpoint 的支持,如果你使用的不同目录下的一样命名的模板文件,那么就会出现问题了。

先摆事实、再讲道理。

明了问题所在

实例项目的目录结构如下:

app
├── admin
│   ├── errors.py
│   ├── forms.py
│   ├── __init__.py
│   ├── static
│   │   ├── css
│   ├── templates
│   │   ├── index.html
│   ├── views.py
├── __init__.py
├── main
│   ├── errors.py
│   ├── forms.py
│   ├── __init__.py
│   ├── templates
│   │   └── ousi
│   │       ├── index.html
│   │       ├── static
│   │       │   ├── css
│   ├── views.py
├── models.py

该项目中注册两个 Blueprint,即 admin 是所谓的后台管理蓝图,main 是所谓的前台展示蓝图。
蓝图 admin 的 __init__.py 内容如下:

# -*- coding:utf-8 -*-
__author__ = "东方鹗"


from flask import Blueprint

admin = Blueprint("admin", __name__, template_folder="templates", static_folder="static")

# 在末尾导入相关模块,是为了避免循环导入依赖,因为在下面的模块中还要导入蓝本main
from . import views, errors

蓝图 main 的 __init__.py 内容如下:

# -*- coding:utf-8 -*-
__author__ = "东方鹗"


from flask import Blueprint


main = Blueprint("main", __name__, template_folder="templates/ousi",
                                 static_folder="templates/ousi/static")

# 在末尾导入相关模块,是为了避免循环导入依赖,因为在下面的模块中还要导入蓝本main
from . import views, errors

在定义两个蓝图的时候,也对本蓝图所对应的模板文件夹和静态文件夹进行了定义,此文主要关注模板文件夹

那么,现在就说说出现了什么问题。

在各自蓝图的视图函数中都对主页 "/" 或叫做 "index" 进行了定义。

其中,蓝图 admin 的视图函数定义如下:

@admin.route("/", methods=["GET", "POST"])
@login_required
def index():

    return render_template("index.html")

请记住最后的代码,即 render_template("index.html"),此处调用的模板名叫做 index.html

蓝图 admin 的视图函数定义如下:

@main.route("/", methods=["GET", "POST"])
def index():

    return render_template("index.html")

请记住最后的代码,即 render_template("index.html"),此处调用的模板名叫做 index.html

到此,你发现了什么,你发现了什么,我估计你已经看出来两个视图函数的最后一行代码是一样的,说得再精确点,调用的模板名是一样的。但是此处我们要保持清醒,虽然模板名称一样,但是所在目录是不一样的,它们所处的位置是各自所在的蓝图所定义的模板文件夹里。

说了这么多,到底怎么了呢。

这时,如果你测试一下你的程序的话,你会发现两个蓝图所显示的内容是一样的,不管你相信不相信自己的眼睛,它就是一样的界面,而且绝对一样,因为 render_template("index.html") 调用的是同一个模板,它可不会区分蓝图。

那么,到底调用的是那个蓝图下的模板呢??继续往下看。

这时你打开 app/__init__.py,内容如下:

def create_app(config_name):
    """ 使用工厂函数初始化程序实例"""
    app = Flask(__name__)
    app.config.from_object(config[config_name])
    config[config_name].init_app(app=app)

    # mail.init_app(app=app)
    moment.init_app(app=app)
    db.init_app(app=app)
    md.init_app(app=app)
    login_manager.init_app(app=app)

    # 注册蓝本 main
    from .main import main as main_blueprint
    app.register_blueprint(main_blueprint, url_prefix="/main")

    # 注册蓝本 admin
    from .admin import admin as admin_blueprint
    app.register_blueprint(admin_blueprint, url_prefix="/admin")

    # 注册蓝本 main
    #from .main import main as main_blueprint
    #app.register_blueprint(main_blueprint, url_prefix="/dynamic")

    return app

到底调用的是那个蓝图下的模板呢??

这个,我可以明确告诉你,main 和 admin 两个蓝图,哪个在 app/__init__.py 中先注册,就调用那个蓝图的模板,也就是说哪个蓝图注册时所用的代码写得靠上,就调用那个蓝图的模板。

这到底是为什么呢?为什么呢?这是 flask 项目的一个小 bug。写项目的时候,要注意此坑,render_template() 函数里所调用的模板一定要保证命名在整个项目中的唯一性。

号外,号外

今天又发现了一个坑,就是 jinja2 内部的模板调用,比如 include 某某模板的时候,这个被调用的模板名称也需要,而且强烈需要保证在整个项目,记住是整个项目中,其命名要具有唯一性。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/44506.html

相关文章

  • flask之三:视图高级

    摘要:视图高级和这个方法是用来添加与视图函数的映射。小例子如下请求上下文的定义,结合类视图之前我们接触的视图都是函数,所以一般简称视图函数。 视图高级 app.route和app.add_url_rule app.add_url_rule app.add_url_rule(/list/,endpoint=myweb,view_func=my_list) 这个方法是用来添加url与视图函数...

    hot_pot_Leo 评论0 收藏0
  • flask之三:视图高级

    摘要:视图高级和这个方法是用来添加与视图函数的映射。小例子如下请求上下文的定义,结合类视图之前我们接触的视图都是函数,所以一般简称视图函数。 视图高级 app.route和app.add_url_rule app.add_url_rule app.add_url_rule(/list/,endpoint=myweb,view_func=my_list) 这个方法是用来添加url与视图函数...

    RancherLabs 评论0 收藏0
  • flask之三:视图高级

    摘要:视图高级和这个方法是用来添加与视图函数的映射。小例子如下请求上下文的定义,结合类视图之前我们接触的视图都是函数,所以一般简称视图函数。 视图高级 app.route和app.add_url_rule app.add_url_rule app.add_url_rule(/list/,endpoint=myweb,view_func=my_list) 这个方法是用来添加url与视图函数...

    xumenger 评论0 收藏0
  • Flask Web Development —— 大型应用程序结构(上)

    摘要:被定义在包的构造函数中的应用程序工厂函数会在示例中展示。这个构造函数导入大部分当前需要使用的扩展,但因为没有应用程序实例初始化它们,它可以被创建但不初始化通过不传递参数给它们的构造函数。而应用程序范围内的错误处理则必须使用。 虽然小型web应用程序用单个脚本可以很方便,但这种方法却不能很好地扩展。随着应用变得复杂,在单个大的源文件中处理会变得问题重重。 与大多数其他web框架不同,Fl...

    chemzqm 评论0 收藏0

发表评论

0条评论

stonezhu

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<