Flask中'endpoint'(端点)的理解
Posted yanzi_meng
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flask中'endpoint'(端点)的理解相关的知识,希望对你有一定的参考价值。
翻译整理自Stack Overflow:http://stackoverflow.com/questions/19261833/what-is-an-endpoint-in-flask
原文中用到了my_greeting
视图函数/端点,我估计是答者笔误,故修改为了give_greeting
。
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
函数。
然而,当我们用这种最常用的方法创建视图时,flask却向我们隐藏了一些其他的细节信息。在这个场景中,flask并没有直接从URL地址跳转到应该响应它请求的视图函数上:
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'(端点)的理解的主要内容,如果未能解决你的问题,请参考以下文章
flask中的endpoint自定义转化器与djnago中session区别利用装饰器实现登录认证
flask报错:werkzeug.routing.BuildError: Could not build url for endpoint 'index'. Did you mean