flask (app.route内部实现)

记录一下app.route()的大致工作原理

一个最小的flask应用

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    app.run()

1.route的源码

    def route(self, rule, **options):
        """A decorator that is used to register a view function for a
        given URL rule.  This does the same thing as :meth:`add_url_rule`
        but is intended for decorator usage::

            @app.route('/')
            def index():
                return 'Hello World'

        """

        def decorator(f):
            endpoint = options.pop('endpoint', None)
            self.add_url_rule(rule, endpoint, f, **options)
            return f

        return decorator

route是一个带参数的装饰器,它实际上就做一件事情:调用add_url_rule(rule, endpoint, f),然后返回f。这里说明一下add_url_rule方法里面的三个参数。

  1. rule:就是装饰器传递过来的url("/")
  2. endpoint:endpoint与一个视图函数绑定,当调用 url_for(endpoint) 时返回绑定的视图函数的url,endpoint的值默认就是绑定的视图函数的函数名,后面会讲到为什么默认是函数名。此处由于并没有传递options参数过来,所以此时endpoint为空。
  3. f:就是被装饰的函数(hello_world)

2.add_url_rule源码

@setupmethod
def add_url_rule(self, rule, endpoint=None, view_func=None,
                    provide_automatic_options=None, **options):

    ...  # 源码块1

    if endpoint is None:
        endpoint = _endpoint_from_view_func(view_func)
    options['endpoint'] = endpoint
  

    ...  # 源码块2 
    methods = options.pop('methods', None)

    if methods is None:
        methods = getattr(view_func, 'methods', None) or ('GET',)
    if isinstance(methods, string_types):
        raise TypeError('Allowed methods have to be iterables of strings, '
                          'for example: @app.route(..., methods=["POST"])')
    methods = set(item.upper() for item in methods)
    
    ...

2.1源码块1分析:

由于此处传递过来的endpoint为None,所以执行了if里面的语句,即将_endpoint_from_view_func(view_func)的返回值赋给了endpoint。此时view_func即为传递过来的 f。来看一下_endpoint_from_view_func(view_func)到底返回了什么。

def _endpoint_from_view_func(view_func):
    """Internal helper that returns the default endpoint for a given
    function.  This always is the function name.
    """
    assert view_func is not None, 'expected view func if endpoint is not provided.'
    return view_func.__name__

可以看到它返回了视图函数的名字,这就解释了endpoint的值为什么默认就是绑定的视图函数的函数名。

2.2源码块2分析:

如果在定义视图函数的时候不指定methods,那么methods就为None,接着就会调用 getattr(view_func, 'methods', None),结合给methods赋值,这里解释了为什么试图函数的默认method为GET。

先分析这么多,再往后面的源码没看太懂。

总结:

  • 绑定视图函数有两种方式
  1. 装饰器的方式,即app.route()。
  2. 直接调用 app.add_url_rule(url, endpoint, view_fun)。
  • 最终将试图函数添加到了view_functions中。

 

参考:https://blog.csdn.net/f704084109/article/details/80708107 

你可能感兴趣的:(python)