Flask中'endpoint'(端點)的理解
Flask路由是如何工作的
整個flask框架(及以Werkzeug類庫為基礎構建的應用)的程序理念是把URL地址映射到你想要運行的業務邏輯上(最典型的就是視圖函數),例如:
@app.route(‘/greeting/<name>‘)
def give_greeting(name):
return ‘Hello, {0}!‘.format(name)
- 1
- 2
- 3
註意,add_url_rule函數實現了同樣的目的,只不過沒有使用裝飾器,因此,下面的程序是等價的:
# 擡頭沒有使用路由裝飾器,我們在最後用另一種方法添加路由.
def give_greeting(name):
return ‘Hello, {0}!‘.format(name)
app.add_url_rule(‘/greeting/<name>‘, ‘give_greeting‘, give_greeting)
- 1
- 2
- 3
- 4
- 5
備註:add_url_rule()中3個參數依次是rule、view_func、endpoint.
假設www.example.org站點定義了以上視圖,用戶在瀏覽器中輸入以下地址
http://www.example.org/greeting/Mark
- 1
Flask的工作就是捕捉這個URL地址,弄清用戶想要做什麽,並在眾多的Python函數中匹配一個可以處理它的函數,回到我們的實例中,URL地址就是
/greeting/Mark
- 1
拿著這個地址到路由表中做匹配,flask發現這個地址指向了give_greeting
函數。
URL (http://www.example.org/greeting/Mark) 被視圖函數處理 ("give_greeting"函數)
- 1
事實上,這裏還有另一個步驟–把URL地址映射到端點上(URL**–>endpoint–>**viewfunction):
URL (http://www.example.org/greeting/Mark) 映射到端點"give_greeting"上.
指向端點"give_greeting"的請求被視圖函數"give_greeting"處理.
- 1
- 2
從根本上來說,端點就是程序中一組邏輯處理單元的ID,該ID對應的代碼決定了對此ID請求應該作出何種響應。通常,端點與視圖函數同名,但是你也可以修改它,例如:
@app.route(‘/greeting/<name>‘, endpoint=‘say_hello‘)
def give_greeting(name):
return ‘Hello, {0}!‘.format(name)
- 1
- 2
- 3
現在就成了這樣:
URL (http://www.example.org/greeting/Mark) 映射到端點"say_hello"上.
指向端點"say_hello"的請求被視圖函數"give_greeting"處理.
- 1
- 2
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/<name>‘)
def give_greeting(name):
return ‘Hello, {0}!‘.format(name)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
備註:url_for()中
give_greeting
是端點名.
這樣做是大有裨益的:我們可以隨意改變應用中的URL地址,卻不用修改與之關聯的資源的代碼。
為何要多此一舉
那麽問題來了:為何要多此一舉,為何要先把URL映射到端點上,再通過端點映射到視圖函數上,為何不跳過中間的這個步驟?
原因就是采用這種方法能夠使程序更高、更快、更強。例如藍本。藍本允許我們把應用分割為一個個小的部分,現在admin藍本中含有超級管理員級的資源,user藍本中則含有用戶一級的資源。
藍本允許咱們把應用分割為一個個以命名空間區分的小部分:
main.py:
from flask import Flask, Blueprint
from admin import admin
from user import user
app = Flask(__name__)
app.register_blueprint(admin, url_prefix=‘admin‘)
app.register_blueprint(user, url_prefix=‘user‘)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
admin.py:
admin = Blueprint(‘admin‘, __name__)
@admin.route(‘/greeting‘)
def greeting():
return ‘Hello, administrative user!‘
- 1
- 2
- 3
- 4
- 5
user.py:
user = Blueprint(‘user‘, __name__)
@user.route(‘/greeting‘)
def greeting():
return ‘Hello, lowly normal user!‘
- 1
- 2
- 3
- 4
註意,在兩個藍本中路由地址‘/greeting’的函數都叫"greeting"
。如果我想調用admin對應的greeting
函數,我不能說“我想要greeting”,因為這裏還有一個user對應的greeting
函數。端點這時就發揮作用了:指定一個藍本名稱作為端點的一部分–通過這種方式端點實現了對命名空間的支持。所以,我們可以這樣寫:
print url_for(‘admin.greeting‘) # Prints ‘/admin/greeting‘
print url_for(‘user.greeting‘) # Prints ‘/user/greeting‘
- 1
- 2
來發實例
from flask import Flask, url_for
app = Flask(__name__)
# We can use url_for(‘foo_view‘) for reverse-lookups in templates or view functions
@app.route(‘/foo‘)
def foo_view():
pass
# We now specify the custom endpoint named ‘bufar‘. url_for(‘bar_view‘) will fail!
@app.route(‘/bar‘, endpoint=‘bufar‘)
def bar_view():
pass
with app.test_request_context(‘/‘):
print (url_for(‘foo_view‘)) #/foo
print (url_for(‘bufar‘)) #/bar
# url_for(‘bar_view‘) will raise werkzeug.routing.BuildError
print (url_for(‘bar_view‘)) #端點bar_view是沒有定義的
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
程序運行結果
更多參考:
Flask中'endpoint'(端點)的理解