zoukankan      html  css  js  c++  java
  • 使用 Blueprint 要注意 render_template 函数

    此文章主要是为了记录在使用 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 某某模板的时候,这个被调用的模板名称也需要,而且强烈需要保证在整个项目,记住是整个项目中,其命名要具有唯一性。

  • 相关阅读:
    Math 类、Random 类、BigDecimal 类
    Redis 持久化原理及过期 key 清除策略
    MySql 存储引擎和索引
    MySql 视图、触发器以及存储过程
    布隆过滤器
    微信红包实现原理
    11-散列3 QQ帐户的申请与登陆 (25 分)
    11-散列2 Hashing (25 分)
    11-散列1 电话聊天狂人 (25 分)
    C语言实现Linux之ls
  • 原文地址:https://www.cnblogs.com/10manongit/p/12845920.html
Copyright © 2011-2022 走看看