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的print用法示例
Feb 11 Python
python数据结构链表之单向链表(实例讲解)
Jul 25 Python
python实现远程通过网络邮件控制计算机重启或关机
Feb 22 Python
Window环境下Scrapy开发环境搭建
Nov 18 Python
Jupyter notebook在mac:linux上的配置和远程访问的方法
Jan 14 Python
wxPython绘图模块wxPyPlot实现数据可视化
Nov 19 Python
在Python中使用MongoEngine操作数据库教程实例
Dec 03 Python
python数据库操作mysql:pymysql、sqlalchemy常见用法详解
Mar 30 Python
使用pth文件添加Python环境变量方式
May 26 Python
如何真正的了解python装饰器
Aug 14 Python
python 装饰器的实际作用有哪些
Sep 07 Python
selenium学习教程之定位以及切换frame(iframe)
Jan 04 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
15个小时----从修改程序到自己些程序
2006/10/09 PHP
php采集速度探究总结(原创)
2008/04/18 PHP
浅析is_writable的php实现
2013/06/18 PHP
php中time()与$_SERVER[REQUEST_TIME]用法区别
2014/11/19 PHP
return false,对阻止事件默认动作的一些测试代码
2010/11/17 Javascript
理解JavaScript中的对象 推荐
2011/01/09 Javascript
javascript题目,重写函数让其无限相加
2012/02/15 Javascript
使用jquery.upload.js实现异步上传示例代码
2014/07/29 Javascript
基于NodeJS的前后端分离的思考与实践(四)安全问题解决方案
2014/09/26 NodeJs
asp知识整理笔记3(问答模式)
2015/09/27 Javascript
JS实现消息来时让网页标题闪动效果的方法
2016/04/20 Javascript
浅析Bootstrap缩略图组件与警示框组件
2016/04/29 Javascript
第一次接触神奇的Bootstrap菜单和导航
2016/08/01 Javascript
JQuery页面随滚动条动态加载效果的简单实现(推荐)
2017/02/08 Javascript
在iFrame子页面里实现模态框的方法
2018/08/17 Javascript
vue.js响应式原理解析与实现
2020/06/22 Javascript
从零开始封装自己的自定义Vue组件
2018/10/09 Javascript
详解create-react-app 2.0版本如何启用装饰器语法
2018/10/23 Javascript
JavaScript时间与时间戳的转换操作实例分析
2018/12/07 Javascript
JQuery Ajax如何实现注册检测用户名
2020/09/25 jQuery
Python中decorator使用实例
2015/04/14 Python
Python处理PDF及生成多层PDF实例代码
2017/04/24 Python
python中with用法讲解
2020/02/07 Python
浅谈OpenCV中的新函数connectedComponentsWithStats用法
2020/07/05 Python
Python创建简单的神经网络实例讲解
2021/01/04 Python
前端制作动画的几种方式(css3,js)
2016/12/12 HTML / CSS
戴尔加拿大官网:Dell加拿大
2016/09/17 全球购物
澳大利亚领先的在线礼品网站:Gifts Australia
2020/08/15 全球购物
乡镇干部十八大感言
2014/02/17 职场文书
机械设计制造及其自动化专业求职信
2014/06/17 职场文书
公司周年庆典标语
2014/10/07 职场文书
2014年信用社工作总结
2014/11/25 职场文书
数学教师求职信范文
2015/03/20 职场文书
工厂员工辞职信范文
2015/05/12 职场文书
python 管理系统实现mysql交互的示例代码
2021/12/06 Python
Ruby使用Mysql2连接操作MySQL
2022/04/19 Ruby