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中关于时间和日期函数的常用计算总结(time和datatime)
Mar 08 Python
pygame学习笔记(6):完成一个简单的游戏
Apr 15 Python
Python NumPy库安装使用笔记
May 18 Python
详解Python中映射类型的内建函数和工厂函数
Aug 19 Python
Python实现SSH远程登陆,并执行命令的方法(分享)
May 08 Python
python中hashlib模块用法示例
Oct 30 Python
Python方法的延迟加载的示例代码
Dec 18 Python
Python3实现取图片中特定的像素替换指定的颜色示例
Jan 24 Python
利用4行Python代码监测每一行程序的运行时间和空间消耗
Apr 22 Python
python -v 报错问题的解决方法
Sep 15 Python
Selenium关闭INFO:CONSOLE提示的解决
Dec 07 Python
Python - 10行代码集2000张美女图
May 23 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 中执行排序与 MySQL 中排序
2009/04/21 PHP
PHP 多进程 解决难题
2009/06/22 PHP
php实现保存submit内容之后禁止刷新
2014/03/19 PHP
PHP实现对文本数据库的常用操作方法实例演示
2014/07/04 PHP
PHPStrom中实用的功能和快捷键大全
2015/09/23 PHP
laravel自定义分页的实现案例offset()和limit()
2019/10/15 PHP
JavaScript入门教程(2) JS基础知识
2009/01/31 Javascript
基于jquery的当鼠标滚轮到最底端继续加载新数据思路分享(多用于微博、空间、论坛 )
2011/10/10 Javascript
jQuery操作input type=radio的实现代码
2012/06/14 Javascript
extjs表格文本启用选择复制功能具体实现
2013/10/11 Javascript
利用JQuery写一个简单的异步分页插件
2016/03/07 Javascript
js仿支付宝填写支付密码效果实现多方框输入密码
2016/03/09 Javascript
vue.js实现含搜索的多种复选框(附源码)
2017/03/23 Javascript
nodejs入门教程五:连接数据库的方法分析
2017/04/24 NodeJs
使用jQuery实现购物车结算功能
2017/08/15 jQuery
vue-router相关基础知识及工作原理
2018/03/16 Javascript
JavaScript实现shuffle数组洗牌操作示例
2019/01/03 Javascript
写给新手同学的vuex快速上手指北小结
2020/04/14 Javascript
vue 封装面包屑组件教程
2020/11/16 Javascript
原生js实现九宫格拖拽换位
2021/01/26 Javascript
[04:09]2014DOTA2国际邀请赛Ti西雅图 历届冠军相继出局 BBC综述今日比赛
2014/07/20 DOTA
[01:20:05]DOTA2-DPC中国联赛 正赛 Ehome vs VG BO3 第二场 2月5日
2021/03/11 DOTA
python33 urllib2使用方法细节讲解
2013/12/03 Python
Python编程之黑板上排列组合,你舍得解开吗
2017/10/30 Python
python中的RSA加密与解密实例解析
2019/11/18 Python
Python 捕获代码中所有异常的方法
2020/08/03 Python
日本民宿预约平台:STAY JAPAN
2017/07/01 全球购物
澳大利亚买卖正宗二手奢侈品交易平台:Luxe.It.Fwd
2019/10/16 全球购物
DataList 能否分页,请问如何实现?
2015/05/03 面试题
办公室综合文员岗位职责范本
2014/02/13 职场文书
校园安全广播稿范文
2014/09/25 职场文书
党员三严三实心得体会
2014/10/13 职场文书
2015年世界无烟日活动总结
2015/02/10 职场文书
匿名信格式范文
2015/05/27 职场文书
钢铁是怎样炼成的读书笔记
2015/06/29 职场文书
Java 数组内置函数toArray详解
2021/06/28 Java/Android