此文章主要是為了記錄在使用 Flask 的過程中遇到的問題王浴。本章主要討論 render_template 函數(shù)的問題柔吼。
使用 Flask 的同學都應該知道,項目中的 url 和視圖函數(shù)是在字典里一一對應著的,再詳細一點,就是 url 對應著 endpoint肩民,視圖函數(shù)也對應著 endpoint,并且 endpoint 在字典里是唯一存在的撬槽。
而對于不同 Blueprint 里的 url,是依靠所注冊的藍圖以及不同的前綴來進行區(qū)分趾撵。但是在視圖函數(shù)中所調(diào)用的 render_template 函數(shù)可得不到 endpoint 的支持侄柔,如果你使用的不同目錄下的一樣命名的模板文件,那么就會出現(xiàn)問題了占调。
先擺事實暂题、再講道理。
明了問題所在
實例項目的目錄結(jié)構(gòu)如下:
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 內(nèi)容如下:
# -*- coding:utf-8 -*-
__author__ = '東方鶚'
from flask import Blueprint
admin = Blueprint('admin', __name__, template_folder="templates", static_folder='static')
# 在末尾導入相關(guān)模塊剿涮,是為了避免循環(huán)導入依賴言津,因為在下面的模塊中還要導入藍本main
from . import views, errors
藍圖 main 的 __init__.py 內(nèi)容如下:
# -*- coding:utf-8 -*-
__author__ = '東方鶚'
from flask import Blueprint
main = Blueprint('main', __name__, template_folder="templates/ousi",
static_folder='templates/ousi/static')
# 在末尾導入相關(guān)模塊攻人,是為了避免循環(huán)導入依賴,因為在下面的模塊中還要導入藍本main
from . import views, errors
在定義兩個藍圖的時候悬槽,也對本藍圖所對應的模板文件夾和靜態(tài)文件夾進行了定義怀吻,此文主要關(guān)注模板文件夾。
那么初婆,現(xiàn)在就說說出現(xiàn)了什么問題蓬坡。
在各自藍圖的視圖函數(shù)中都對主頁 '/' 或叫做 'index' 進行了定義。
其中磅叛,藍圖 admin 的視圖函數(shù)定義如下:
@admin.route('/', methods=['GET', 'POST'])
@login_required
def index():
return render_template('index.html')
請記住最后的代碼屑咳,即 render_template('index.html')
,此處調(diào)用的模板名叫做 index.html
弊琴。
藍圖 admin 的視圖函數(shù)定義如下:
@main.route('/', methods=['GET', 'POST'])
def index():
return render_template('index.html')
請記住最后的代碼兆龙,即 render_template('index.html')
,此處調(diào)用的模板名叫做 index.html
访雪。
到此详瑞,你發(fā)現(xiàn)了什么,你發(fā)現(xiàn)了什么臣缀,我估計你已經(jīng)看出來兩個視圖函數(shù)的最后一行代碼是一樣的坝橡,說得再精確點,調(diào)用的模板名是一樣的精置。但是此處我們要保持清醒计寇,雖然模板名稱一樣,但是所在目錄是不一樣的脂倦,它們所處的位置是各自所在的藍圖所定義的模板文件夾里番宁。
說了這么多,到底怎么了呢赖阻。
這時蝶押,如果你測試一下你的程序的話,你會發(fā)現(xiàn)兩個藍圖所顯示的內(nèi)容是一樣的火欧,不管你相信不相信自己的眼睛棋电,它就是一樣的界面,而且絕對一樣苇侵,因為 render_template('index.html')
調(diào)用的是同一個模板赶盔,它可不會區(qū)分藍圖。
那么榆浓,到底調(diào)用的是那個藍圖下的模板呢于未??繼續(xù)往下看。
這時你打開 app/__init__.py烘浦,內(nèi)容如下:
def create_app(config_name):
""" 使用工廠函數(shù)初始化程序?qū)嵗?""
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
到底調(diào)用的是那個藍圖下的模板呢抖坪??
這個谎倔,我可以明確告訴你柳击,main 和 admin 兩個藍圖,哪個在 app/__init__.py 中先注冊片习,就調(diào)用那個藍圖的模板捌肴,也就是說哪個藍圖注冊時所用的代碼寫得靠上,就調(diào)用那個藍圖的模板藕咏。
這到底是為什么呢状知?為什么呢?這是 flask 項目的一個小 bug孽查。寫項目的時候饥悴,要注意此坑,render_template()
函數(shù)里所調(diào)用的模板一定要保證命名在整個項目中的唯一性盲再。
號外西设,號外
今天又發(fā)現(xiàn)了一個坑,就是 jinja2 內(nèi)部的模板調(diào)用答朋,比如 include 某某模板的時候贷揽,這個被調(diào)用的模板名稱也需要,而且強烈需要保證在整個項目梦碗,記住是整個項目中禽绪,其命名要具有唯一性。