Flask中'endpoint'(端點)的理解

可以翻譯成“視圖入口”,就是個名字。url_for可以用到,其他方面也可以用到(比如導航條確定當前頁面),因為endpoint在一個 app 里唯一對應到一個 view function。



翻譯整理自Stack Overflowhttp://stackoverflow.com/questions/19261833/what-is-an-endpoint-in-flask

原文中用到了my_greeting視圖函數/端點,我估計是答者筆誤,故修改為了give_greeting。

Flask路由是如何工作的

整個flask框架(及以Werkzeug類庫為基礎構建的應用)的程序理念是把URL地址映射到你想要運行的業務邏輯上(最典型的就是視圖函數),例如:

@app.route('/greeting/')defgive_greeting(name):return'Hello, {0}!'.format(name)

注意,add_url_rule函數實現了同樣的目的,只不過沒有使用裝飾器,因此,下面的程序是等價的:

# 抬頭沒有使用路由裝飾器,我們在最后用另一種方法添加路由.defgive_greeting(name):return'Hello, {0}!'.format(name)app.add_url_rule('/greeting/','give_greeting', give_greeting)

備注:add_url_rule()中3個參數依次是ruleview_funcendpoint.

假設www.example.org站點定義了以上視圖,用戶在瀏覽器中輸入以下地址

http://www.example.org/greeting/Mark

Flask的工作就是捕捉這個URL地址,弄清用戶想要做什么,并在眾多的Python函數中匹配一個可以處理它的函數,回到我們的實例中,URL地址就是

/greeting/Mark

拿著這個地址到路由表中做匹配,flask發現這個地址指向了give_greeting函數。

然而,當我們用這種最常用的方法創建視圖時,flask卻向我們隱藏了一些其他的細節信息。在這個場景中,flask并沒有直接從URL地址跳轉到應該響應它請求的視圖函數上:

URL (http://www.example.org/greeting/Mark) 被視圖函數處理 ("give_greeting"函數)

事實上,這里還有另一個步驟--把URL地址映射到端點上(URL-->endpoint-->viewfunction):

URL (http://www.example.org/greeting/Mark) 映射到端點"give_greeting"上.指向端點"give_greeting"的請求被視圖函數"give_greeting"處理.

從根本上來說,端點就是程序中一組邏輯處理單元的ID,該ID對應的代碼決定了對此ID請求應該作出何種響應。通常,端點與視圖函數同名,但是你也可以修改它,例如:

@app.route('/greeting/', endpoint='say_hello')defgive_greeting(name):return'Hello, {0}!'.format(name)

現在就成了這樣:

URL (http://www.example.org/greeting/Mark) 映射到端點"say_hello"上.指向端點"say_hello"的請求被視圖函數"give_greeting"處理.

Endpoint有什么作用

端點通常用作反向查詢URL地址(viewfunction-->endpoint-->URL)。例如,在flask中有個視圖,你想把它關聯到另一個視圖上(或從站點的一處連接到另一處)。不用去千辛萬苦的寫它對應的URL地址,直接使用URL_for()就可以啦:

@app.route('/')def index():? ? print url_for('give_greeting', name='Mark') # 打印出'/greeting/Mark'@app.route('/greeting/')def give_greeting(name):? ? return'Hello, {0}!'.format(name)

備注:url_for()中give_greeting是端點名.

這樣做是大有裨益的:我們可以隨意改變應用中的URL地址,卻不用修改與之關聯的資源的代碼。

為何要多此一舉

那么問題來了:為何要多此一舉,為何要先把URL映射到端點上,再通過端點映射到視圖函數上,為何不跳過中間的這個步驟?

原因就是采用這種方法能夠使程序更高、更快、更強。例如藍本。藍本允許我們把應用分割為一個個小的部分,現在admin藍本中含有超級管理員級的資源,user藍本中則含有用戶一級的資源。

藍本允許咱們把應用分割為一個個以命名空間區分的小部分:

main.py:

fromflaskimportFlask, Blueprintfromadminimportadminfromuserimportuserapp = Flask(__name__)app.register_blueprint(admin, url_prefix='admin')app.register_blueprint(user, url_prefix='user')

admin.py:

admin = Blueprint('admin', __name__)@admin.route('/greeting')defgreeting():return'Hello, administrative user!'

user.py:

user = Blueprint('user', __name__)@user.route('/greeting')defgreeting():return'Hello, lowly normal user!'

注意,在兩個藍本中路由地址'/greeting'的函數都叫"greeting"。如果我想調用admin對應的greeting函數,我不能說“我想要greeting”,因為這里還有一個user對應的greeting函數。端點這時就發揮作用了:指定一個藍本名稱作為端點的一部分--通過這種方式端點實現了對命名空間的支持。所以,我們可以這樣寫:

printurl_for('admin.greeting') # Prints'/admin/greeting'printurl_for('user.greeting') # Prints'/user/greeting'

來發實例

fromflaskimportFlask, url_forapp = Flask(__name__)# We can use url_for('foo_view') for reverse-lookups in templates or view functions@app.route('/foo')deffoo_view():pass# We now specify the custom endpoint named 'bufar'. url_for('bar_view') will fail!@app.route('/bar', endpoint='bufar')defbar_view():passwithapp.test_request_context('/'):print(url_for('foo_view'))#/fooprint(url_for('bufar'))#/bar# url_for('bar_view') will raise werkzeug.routing.BuildErrorprint(url_for('bar_view'))#端點bar_view是沒有定義的

程序運行結果

python_endpoint_程序運行結果

更多參考:

http://www.cnblogs.com/eric-nirnava/p/endpoint.html

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容