注册路由

一个 web 应用不同的路径会有不同的处理函数,路由就是根据请求的 URL 找到对应处理函数的过程。

在执行查找之前,需要有一个规则列表,它存储了 url 和处理函数的对应关系。最容易想到的解决方案就是定义一个字典,key 是 url,value 是对应的处理函数。如果 url 都是静态的(url 路径都是实现确定的,没有变量和正则匹配),那么路由的过程就是从字典中通过 url 这个 key ,找到并返回对应的 value;如果没有找到,就报 404 错误。而对于动态路由,还需要更复杂的匹配逻辑。

Flask 中,构建这个路由规则 的两种方法,这两种方法是等价的:

  1. 通过 @app.route() 装饰器
  2. 通过 add_url_rule(self, rule, endpoint=None, view_func=None, **options) 方法:
    • rule: url 规则字符串,
    • endpoint:要注册规则的 endpoint,默认是 view_func 的名字
    • view_func:对应 url 的处理函数,也被称为视图函数

通过 @app.route() 装饰器:

  1. @app.route('/')
  2. def hello():
  3. return "hello, world!"

通过 add_url_rule()

  1. def hello():
  2. return "hello, world!"
  3. app.add_url_rule('/', 'hello', hello)

可以看到 route 方法内部也是调用 add_url_rule 所以注册路由也可以直接使用add_url_rule实现

  1. def route(self, rule, **options):
  2. """A decorator that is used to register a view function for a
  3. given URL rule. This does the same thing as :meth:`add_url_rule`
  4. but is intended for decorator usage.
  5. """
  6. def decorator(f):
  7. endpoint = options.pop('endpoint', None)
  8. self.add_url_rule(rule, endpoint, f, **options)
  9. return f
  10. return decorator

add_url_rule 核心代码如下:

  1. def add_url_rule(
  2. self,
  3. rule,
  4. endpoint=None,
  5. view_func=None,
  6. provide_automatic_options=None,
  7. **options
  8. ):
  9. rule = self.url_rule_class(rule, methods=methods, **options)
  10. rule.provide_automatic_options = provide_automatic_options
  11. self.url_map.add(rule)
  12. if view_func is not None:
  13. old_func = self.view_functions.get(endpoint)
  14. if old_func is not None and old_func != view_func:
  15. raise AssertionError(
  16. "View function mapping is overwriting an "
  17. "existing endpoint function: %s" % endpoint
  18. )
  19. self.view_functions[endpoint] = view_func

Werkzeug 路由逻辑

Flask 路由实现