我一直以為 Blueprint 中的 name 參數(shù)和 url_for 中所用到的 endpoint (端點(diǎn))有關(guān)洪添,下面是我為什么這樣理解的垦页。
1、問題
通常我們?cè)?flask 項(xiàng)目中使用藍(lán)圖的時(shí)候是這樣定義藍(lán)圖的:
admin = Blueprint('666', __name__)
其中干奢,第一個(gè)參數(shù)究竟有什么作用痊焊?能否隨便命名,或者干脆不命名忿峻?薄啥?
答案是 否定的!9渖小垄惧!
2、解惑
首先绰寞,我們看一下 flask 的源碼: https://github.com/pallets/flask/blob/master/flask/blueprints.py
其中到逊,有下面的代碼:
class Blueprint(_PackageBoundObject):
...
...
def __init__(self, name, import_name, static_folder=None,
static_url_path=None, template_folder=None,
url_prefix=None, subdomain=None, url_defaults=None,
root_path=None):
_PackageBoundObject.__init__(self, import_name, template_folder,
root_path=root_path)
self.name = name
self.url_prefix = url_prefix
self.subdomain = subdomain
self.static_folder = static_folder
self.static_url_path = static_url_path
self.deferred_functions = []
if url_defaults is None:
url_defaults = {}
self.url_values_defaults = url_defaults
上面的代碼可以明顯的看到, Blueprint 類繼承與 _PackageBoundObject滤钱,其中蕾管,name 參數(shù),可是該類自己定義的菩暗,不是繼承的掰曾,那么,我們繼續(xù)在源碼中查找 name 參數(shù)的作用停团。
在該類中尋找 self.name旷坦, 我們可以看到另外 8 處內(nèi)容掏熬, 分別在該類的 before_request、afte\r_request秒梅、teardown_request旗芬、context_processor、url_value_preprocessor捆蜀、url_defaults疮丛、errorhandler、register_error_handle 這 8 個(gè)類函數(shù)中辆它,基本上函數(shù)中用到的地方都是:
self.record_once(lambda s: s.app.before_request_funcs
.setdefault(self.name, []).append(f))
那么誊薄,我們?cè)倏纯催@個(gè) record_once 函數(shù)的作用,該函數(shù)也是在該類中定義的锰茉。
def record_once(self, func):
"""Works like :meth:`record` but wraps the function in another
function that will ensure the function is only called once. If the
blueprint is registered a second time on the application, the
function passed is not called.
"""
def wrapper(state):
if state.first_registration:
func(state)
return self.record(update_wrapper(wrapper, func))
通過注釋呢蔫,很明顯地看到這個(gè)函數(shù)的作用是為了將 name 參數(shù)作為唯一標(biāo)識(shí),在程序上下文中區(qū)分藍(lán)圖所用的。
那么飒筑,回到原來的問題片吊。
一、之所以可以隨便定義名稱协屡,感覺沒有什么影響俏脊,那是錯(cuò)覺。
- 第一個(gè)原因肤晓,很多時(shí)候联予,我們僅僅只是定義了一個(gè)藍(lán)圖,如果你再定義一個(gè)材原,你把 兩個(gè)藍(lán)圖的 name 參數(shù)設(shè)置成一樣的沸久,你試試程序會(huì)不會(huì)報(bào)錯(cuò)。
- 第二個(gè)原因余蟹,沒有用到 url_for 函數(shù)卷胯,這個(gè)函數(shù)中會(huì)用到藍(lán)圖的 name 參數(shù),或者我們直接這樣簡(jiǎn)化的調(diào)用 url_for('.index') 函數(shù)威酒, 那個(gè) '.' 代表了當(dāng)前的藍(lán)圖窑睁。
- 還是回到 url_for 函數(shù),如果在 html 的 jinja2 中調(diào)用葵孤,得這樣寫 url_for('name.index')担钮,其中的 name 就是藍(lán)圖的 name 參數(shù)。
二尤仍、建議大家試試如果不定義 name 參數(shù)箫津,程序會(huì)不會(huì)報(bào)錯(cuò)。結(jié)果是必定報(bào)錯(cuò),因?yàn)檫@個(gè)參數(shù)是必須的苏遥。
- 在 view 視圖中饼拍,我們使用 裝飾器 的寫法,一般是把函數(shù)名稱當(dāng)做 endpoint 的田炭,如果你在兩個(gè)不同的藍(lán)圖中师抄,使用同一個(gè)名稱來定義視圖函數(shù),那么 endpoint 按照默認(rèn)方案就無法是 唯一標(biāo)識(shí) 了教硫,必須得加上藍(lán)圖的名稱叨吮,所以藍(lán)圖的名稱也得是唯一的。