使用 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 某某模板的时候,这个被调用的模板名称也需要,而且强烈需要保证在整个项目,记住是整个项目中,其命名要具有唯一性。
使用 Blueprint 要注意 render_template 函数的更多相关文章
- 实验4、Flask基于Blueprint & Bootstrap布局的应用服务
1. 实验内容 模块化工程内容能够更好的与项目组内成员合作,Flask Blueprint提供了重要的模块化功能,使得开发过程更加清晰便利.此外,Flask也支持Bootstrap的使用. 2. 实验 ...
- render_template 网页模板
模板简单介绍: 视图函数:视图函数就是装饰器所装饰的方法,视图函数的主要作用是生成请求的响应,这是最简单的请求.实际上,视图函数有两个作用:处理业务逻辑和返回响应内容.在大型应用中,把业务逻辑和表现内 ...
- Flask从入门到精通之在视图函数中处理表单
在新版hello.py 中,视图函数index() 不仅要渲染表单,还要接收表单中的数据.更新后的index() 视图函数如下: @app.route('/') def index(): name = ...
- flask中Flask()和Blueprint() flask中的g、add_url_rule、send_from_directory、static_url_path、static_folder的用法
1.Blueprint()在蓝本注册函数register_blueprint()中,第一个参数为所注册的蓝本名称.当我们在应用对象上注册一个蓝图时,需要指定一个url_prefix关键字 参数(这个参 ...
- Flask框架函数
title: flask学习笔记 subtitle: 1. flask框架函数 date: 2018-12-14 10:17:28 --- Flask学习 学习Miguel Grinberg的2017 ...
- 用 Flask 来写个轻博客 (11) — M(V)C_创建视图函数
目录 目录 前文列表 视图函数 在 viewspy 文件中定义视图函数 定义右侧边栏的视图函数 为每一张数据表定义视图函数 前文列表 用 Flask 来写个轻博客 (1) - 创建项目 用 Flask ...
- Inside Flask - app.py - 2
Inside Flask - app.py - 2 Flask 初始化参数 Flass 类是 Flask 框架的核心,一个 flask 对象处理视图函数注册.URL规则.模板配置.参数设置等等. 一般 ...
- Flask蓝图
它的作用就是将 功能 与 主服务 分开怎么理解呢? 比如说,你有一个客户管理系统,最开始的时候,只有一个查看客户列表的功能,后来你又加入了一个添加客户的功能(add_user)模块, 然后又加入了一个 ...
- 欢迎来到 Flask 的世界
欢迎来到 Flask 的世界 欢迎阅读 Flask 的文档.本文档分成几个部分,我推荐您先读 < 安装 >,然后读< 快速上手 >.< 教程 > 比快速上手文档更详 ...
随机推荐
- Spark中的Wordcount
目录 通过scala语言基于local编写spark的Wordcount 基于yarn去调度WordCount 通过scala语言基于local编写spark的Wordcount import org ...
- ssl 证书配置
方式1: 1:找见域名列表 2: 主机记录 *,@,www 2:证书申请并下载 3: 4:宝塔网站ssl 参考博客: https://developer.aliyun.com/article/7714 ...
- php 23种设计模型 - 原型模式
原型模式(Prototype) 原型模式(Prototype Pattern)是用于创建重复的对象,同时又能保证性能.这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式. 这种模式是实现 ...
- linux 配置redis密码
1.打开redis配置文件 vi /usr/local/redis/etc/redis.conf 添加requirepass 密码 将bind 127.0.0.1 ::1前的#去掉 保存退出 2 ...
- 编译OneAPI(支持Nvidia显卡)
开始使用DPC++ 官方安装教程 预备条件 请确保当前开发环境满足如下条件: git cmake版本需要满足3.14及以上. python版本3.6以上的python. nijia版本1.8及以上(使 ...
- Xgboost的基本使用
import xgboost as xgb from sklearn.model_selection import train_test_split import pandas as pd data ...
- 顺序表的插入和删除(基于c语言)
插入:在下标p处插入数据x:返回是否成功(0/1) 几个注意点:1.还能否插入数据:2.给的下标p是否是错误的以及p的范围:3.移动时的易错点(从下标大的元素开始):4.n与palist->n; ...
- springsecurity-01-0511
springsecurity-01-0511课堂代码 BaseController package com.springsecurity.springsecurity.controller; impo ...
- NLP 自然语言处理实战
前言 自然语言处理 ( Natural Language Processing, NLP) 是计算机科学领域与人工智能领域中的一个重要方向.它研究能实现人与计算机之间用自然语言进行有效通信的各种理论和 ...
- babel和polyfill?
Babel: Babel 是一个广泛使用的 ES6 转码器,可以将 ES6 代码转为 ES5 代码.注意:Babel 默认只转换新的 JavaScript 句法(syntax),而不转换新的 API ...