读Flask:dispatch_request

之前读到 app.route 实际上是调用 add_url_rule 函数,主要做了两件事:

  1. 注册 view_func 到Flask实例
  2. 建立一个Rule实例,绑定Rule实例到Map实例
    那收到一个匹配Map中某个Rule之后,怎么再call到原来的 view_func 呢?
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    def match_request(self):
    # _request_ctx_stack是一个stack类型的数列
    # 里面存储的是_RequestContext实例
    # 这个实例的url_adapter是Flask实例的Map实例所返回的MapAdapter实例
    # MapAdapter实例的match函数遍历Map实例中的所有Rule实例,执行Rule实例的match函数
    # Rule实例的match函数返回rule所绑定的endpoint和其它参数
    rv = _request_ctx_stack.top.url_adapter.match()
    # 解析出endpoint和其它参数
    request.endpoint, request.view_args = rv
    return rv

    def dispatch_request(self):
    try:
    # 获得endpoint和参数
    endpoint, values = self.match_request()
    # 根据endpoint在view_funcs字典中找出函数,传入参数
    return self.view_functions[endpoint](**values)

    # 如果HTTP类型报错
    except HTTPException, e:
    # 检查是否有自定义error_handler
    handler = self.error_handlers.get(e.code)
    # 没有,返回错误
    if handler is None:
    return e
    # 有,执行error handler, 传入错误代码作为参数
    return handler(e)

    # 其它类型报错
    except Exception, e:
    # 类似上面的过程,不过只搜寻500 error handler
    handler = self.error_handlers.get(500)
    if self.debug or handler is None:
    raise
    return handler(e)
    # 由错误处理过程也可以知道,@error_handle所注册的函数,是以错误代码为id的
    从这里可以知道,Flask每收到一次request时,都会遍历一次map, 执行map中每个rule的match函数,根据request路径进行匹配,如果匹配成功则获得endpoint和参数,再根据字典获得view_func,并传入参数。