Flask中endpoint的理解(小结)


Posted in Python onDecember 11, 2019

在flask框架中,我们经常会遇到endpoint这个东西,最开始也没法理解这个到底是做什么的。最近正好在研究Flask的源码,也就顺带了解了一下这个endpoint

首先,我们看一个例子:

@app.route('/user/<name>')
def user(name):
  return 'Hello, %s' % name

这个是我们在用flask框架写网站中最常用的。

通过看源码,我们可以发现:

函数等效于

def user(name)
  return 'Hello, %s' % name
  
app.add_url_rule('/user/<name>', 'user', user)

这个add_url_rule函数在文档中是这样解释的:

add_url_rule(*args, **kwargs)
 Connects a URL rule. Works exactly like the route() decorator. If a view_func is provided it will be registered with the endpoint.

add_url_rule有如下参数:

rule ? the URL rule as string
endpoint ? the endpoint for the registered URL rule. Flask itself assumes the name of the view function as endpoint
view_func ? the function to call when serving a request to the provided endpoint
options ? the options to be forwarded to the underlying Rule object. A change to Werkzeug is handling of method options. methods is a list of methods this rule should be limited to (GET, POST etc.). By default a rule just listens for GET (and implicitly HEAD). Starting with Flask 0.6, OPTIONS is implicitly added and handled by the standard request handling.

抛开options这个参数不谈,我们看看前三个参数。
rule:这个参数很简单,就是匹配的路由地址
view_func:这个参数就是我们写的视图函数
endpoint:这个参数就是我今天重点要讲的,endpoint

很多人认为:假设用户访问http://www.example.com/user/eric,flask会找到该函数,并传递name='eric',执行这个函数并返回值。

但是实际中,Flask真的是直接根据路由查询视图函数么?

在源码中我们可以发现:

  • 每个应用程序app都有一个view_functions,这是一个字典,存储endpoint-view_func键值对。add_url_rule的第一个作用就是向view_functions中添加键值对(这件事在应用程序run之前就做好了)
  • 每个应用程序app都有一个url_map,它是一个Map类(具体实现在werkzeug/routing.py中),里面包含了一个列表,列表元素是Role的实例(werkzeug/routing.py中)。add_url_rule的第二个作用就是向url_map中添加Role的实例(它也是在应用程序run之前就做好了)

我们可以通过一个例子来看:

app = Flask(__name__)

@app.route('/test', endpoint='Test')
def test():
  pass


@app.route('/', endpoint='index')
def hello_world():
  return 'Hello World!'

if __name__ == '__main__':
  print(app.view_functions)
  print(app.url_map)
  app.run()

运行这个程序,结果是:

{'static': <bound method Flask.send_static_file of <Flask 'flask-code'>>, 'Test': <function test at 0x10065e488>, 'index': <function hello_world at 0x10323d488>}
Map([<Rule '/test' (HEAD, OPTIONS, GET) -> Test>,
 <Rule '/' (HEAD, OPTIONS, GET) -> index>,
 <Rule '/static/<filename>' (HEAD, OPTIONS, GET) -> static>])
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)

所以我们可以看出:这个url_map存储的是url与endpoint的映射!

回到flask接受用户请求地址并查询函数的问题。实际上,当请求传来一个url的时候,会先通过rule找到endpoint(url_map),然后再根据endpoint再找到对应的view_func(view_functions)。通常,endpoint的名字都和视图函数名一样。

这时候,这个endpoint也就好理解了:

实际上这个endpoint就是一个Identifier,每个视图函数都有一个endpoint,

当有请求来到的时候,用它来知道到底使用哪一个视图函数

在实际应用中,当我们需要在一个视图中跳转到另一个视图中的时候,我们经常会使用url_for(endpoint)去查询视图,而不是把地址硬编码到函数中。

这个时候,我们就不能使用视图函数名当endpoint去查询了

我们举个例子来说明。比如:

app = Flask(__name__)
app.register_blueprint(user, url_prefix='user')
app.register_blueprint(file, url_prefix='file')

我们注册了2个蓝图。

在user中(省略初始化过程):

@user.route('/article')
def article():
  pass

在file中(省略初始化过程):

@file.route('/article')
def article():
  pass

这时候,我们发现,/article这个路由对应了两个函数名一样的函数,分别在两个蓝图中。当我们使用url_for(article)调用的时候(注意,url_for是通过endpoint查询url地址,然后找视图函数),flask无法知道到底使用哪个蓝图下的endpoint,所以我们需要这样:

url_for('user.article')

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python采用getopt解析命令行输入参数实例
Sep 30 Python
Python实现的数据结构与算法之队列详解
Apr 22 Python
深入解析Python中的变量和赋值运算符
Oct 12 Python
用yum安装MySQLdb模块的步骤方法
Dec 15 Python
使用Python3制作TCP端口扫描器
Apr 17 Python
Selenium 模拟浏览器动态加载页面的实现方法
May 16 Python
Python3字符串encode与decode的讲解
Apr 02 Python
Python学习笔记之列表推导式实例分析
Aug 13 Python
Python 变量的创建过程详解
Sep 02 Python
浅析PEP570新语法: 只接受位置参数
Oct 15 Python
python rsa-oaep加密的示例代码
Sep 23 Python
Python环境配置实现pip加速过程解析
Nov 27 Python
Python中Flask-RESTful编写API接口(小白入门)
Dec 11 #Python
Python zip函数打包元素实例解析
Dec 11 #Python
基于Python实现扑克牌面试题
Dec 11 #Python
Python如何使用argparse模块处理命令行参数
Dec 11 #Python
opencv3/C++ 平面对象识别&amp;透视变换方式
Dec 11 #Python
Python Lambda函数使用总结详解
Dec 11 #Python
Python迭代器模块itertools使用原理解析
Dec 11 #Python
You might like
php通过字符串调用函数示例
2014/03/02 PHP
php自定义urlencode,urldecode函数实例
2015/03/24 PHP
ThinkPHP开发--使用七牛云储存
2017/09/14 PHP
php实现银联商务公众号+服务窗支付的示例代码
2019/10/12 PHP
JavaScript XML实现两级级联下拉列表
2008/11/10 Javascript
理解JavaScript的caller,callee,call,apply
2009/04/28 Javascript
一句话JavaScript表单验证代码
2009/08/02 Javascript
Extjs优化(二)Form表单提交通用实现
2013/04/15 Javascript
基于javascript滚动图片具体实现
2013/11/18 Javascript
jquery判断页面网址是否有效的两种方法
2016/12/11 Javascript
关于javascript事件响应的基础语法总结(必看篇)
2016/12/26 Javascript
JS实现图片放大缩小的方法
2017/02/15 Javascript
jQuery模拟下拉框选择对应菜单的内容
2017/03/07 Javascript
微信小程序 跳转方式总结
2017/04/20 Javascript
javaScript 逻辑运算符使用技巧整理
2017/05/03 Javascript
微信小程序实现倒计时60s获取验证码
2020/04/17 Javascript
微信小程序获取地理位置及经纬度授权代码实例
2019/09/18 Javascript
layui 上传文件_批量导入数据UI的方法
2019/09/23 Javascript
[05:53]完美世界携手游戏风云打造 卡尔工作室观战系统篇
2013/04/22 DOTA
[04:54]DOTA2 2017国际邀请赛:上届冠军WINGS采访短片
2017/08/09 DOTA
Python os模块中的isfile()和isdir()函数均返回false问题解决方法
2015/02/04 Python
Python FTP两个文件夹间的同步实例代码
2018/05/25 Python
python创造虚拟环境方法总结
2019/03/04 Python
使用Python实现将list中的每一项的首字母大写
2019/06/11 Python
CSS3动画之利用requestAnimationFrame触发重新播放功能
2019/09/11 HTML / CSS
使用css如何制作时间ICON方法实践
2012/11/12 HTML / CSS
html5的websockets全双工通信详解学习示例
2014/02/26 HTML / CSS
Perricone MD裴礼康美国官网:抗衰老护肤品
2016/09/26 全球购物
买卖合同协议书范本
2014/10/18 职场文书
党的群众路线学习笔记
2014/11/06 职场文书
党建工作目标管理责任书
2015/01/29 职场文书
2015年化验室工作总结
2015/04/23 职场文书
傅雷家书读书笔记
2015/06/29 职场文书
获奖感言怎么写
2015/07/31 职场文书
一个成功的互联网创业项目,必须满足这些要求
2019/08/23 职场文书
mybatis使用oracle进行添加数据的方法
2021/04/27 Oracle