当前位置 主页 > 服务器问题 > Linux/apache问题 >

    Flask中endpoint的理解(小结)

    栏目:Linux/apache问题 时间:2019-12-12 10:21

    在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>])