flask源代码笔记——路由

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了flask源代码笔记——路由相关的知识,希望对你有一定的参考价值。

那flask是如何将路由与视图函数绑定的呢?在Flask类的内部是这样定义的:

def route(self, rule, **options):
    def decorator(f):
        self.add_url_rule(rule, f.__name__, **options)
        self.view_functions[f.__name__] = f
        return f
    return decorator

self.view_functions = {}

def add_url_rule(self, rule, endpoint, **options):
    options[endpoint] = endpoint
    options.setdefault(methods, (GET,))
    self.url_map.add(Rule(rule, **options))

self.url_map = Map()

可以看到,route定义了一个装饰品,通过add_url_rule方法将URL与视图函数的名字(即enpoint)绑定,并通过view_function字典将开发者定义的函数添加到视图函数里,形式为{ 函数名: 函数 }。也就是说,URL并不直接与处理函数绑定。URL是与endpoint绑定,而endpoint才与处理函数绑定。endpoint与处理函数通过view_fuction{}字典映射,这很好理解,不过URL与endpoint的绑定就需要多花点心思来理解了,因为引入了werkzeug中的Map和Rule。Map和Rule从字面上很容易理解 为“所有映射关系”和“产生一对新的映射关系”。

Flask类中dispatch_request()方法使用了view_fuction{}字典:

def dispatch_request(self):    
    try:
        endpoint, values = self.match_request()
        return self.view_functions[endpoint](**values)
    except HTTPException, e:
        handler = self.error_handlers.get(e.code)
        if handler is None:
            return e
        return handler(e)
    except Exception, e:
        handler = self.error_handlers.get(500)
        if self.debug or handler is None:
            raise
        return handler(e)

获取endpoint的关键在于match_request()方法:

def match_request(self):
    """Matches the current request against the URL map and also
    stores the endpoint and view arguments on the request object
    is successful, otherwise the exception is stored.
    """
    rv = _request_ctx_stack.top.url_adapter.match()
    request.endpoint, request.view_args = rv
    return rv

这里的match方法是werkzeug中MapAdapter类定义的方法。

>>> m = Map([
...     Rule(/, endpoint=index),
...     Rule(/downloads/, endpoint=downloads/index),
...     Rule(/downloads/<int:id>, endpoint=downloads/show)
... ])
>>> urls = m.bind("example.com", "/")
>>> urls.match("/", "GET")
(index, {})
>>> urls.match("/downloads/42")
(downloads/show, {id: 42})
And here is what happens on redirect and missing URLs:
>>> urls.match("/downloads")
Traceback (most recent call last):
  ...
RequestRedirect: http://example.com/downloads/
>>> urls.match("/missing")
Traceback (most recent call last):
  ...
NotFound: 404 Not Found

这里展示了Map和Rule的主要几个功能:映射关系的添加、绑定和匹配。

总结一下路由匹配的过程:

  1. 通过@app.route或app.add_url_map()将URL和endpoint绑定,将
  2. endpoint和处理函数绑定。
  3. 将请求URL通过match方法取得endpoint及相关参数。
  4. 通过view_fuction{}字典获取endpoint对应的函数,将相关参数传入,进行处理。

以上是关于flask源代码笔记——路由的主要内容,如果未能解决你的问题,请参考以下文章

flask笔记(七):简单路由设置

VSCode自定义代码片段11——vue路由的配置

VSCode自定义代码片段11——vue路由的配置

VSCode自定义代码片段11——vue路由的配置

flask配置参数路由转换器

Flask 笔记一