flask源码分析-如何解析动态路由

达芬奇密码2018-07-19 12:51

问题

在使用flask框架时,经常用到动态路由的特性,如:

@app.route('/user/<int:user_id>')

也比较好奇:

flask是如何解析这种(动态)路由的呢?是通过对字符串特征么,如:":", "<"?

代码跟踪

通过对flask代码的调试跟踪,发现flask是通过正则表达式来分析出动态路由中的转化器转换器参数路由变量的。 当然,flask不是自己来干这事的,而是借助它的依赖werkzeug来实现的。werkzeug是通过正则表达式来实现对路由变量的抽取的,代码如下:

import re
_rule_re = re.compile(r'''
    (?P<static>[^<]*)                           # static rule data
    <
    (?:
        (?P<converter>[a-zA-Z_][a-zA-Z0-9_]*)   # converter name
        (?:\((?P<args>.*?)\))?                  # converter arguments
        \:                                      # variable delimiter
    )?
    (?P<variable>[a-zA-Z_][a-zA-Z0-9_]*)        # variable name
    >
''', re.VERBOSE)
def parse_rule(rule):
    """Parse a rule and return it as generator. Each iteration yields tuples
    in the form ``(converter, arguments, variable)``. If the converter is
    `None` it's a static url part, otherwise it's a dynamic one.
    :internal:
    """
    pos = 0
    end = len(rule)
    do_match = _rule_re.match
    used_names = set()
    while pos < end:
        m = do_match(rule, pos)
        if m is None:
            break
        data = m.groupdict()
        # 内置的
        if data['static']:
            yield None, None, data['static']
        variable = data['variable']
        converter = data['converter'] or 'default'
        # 同一个路由规则中不能使用重复的变量,如:
        # /user/<name>/<name> 是非法的
        if variable in used_names:
            raise ValueError('variable name %r used twice.' % variable)
        used_names.add(variable)
        # 生成器
        yield converter, data['args'] or None, variable
        pos = m.end()
    if pos < end:
        remaining = rule[pos:]
        if '>' in remaining or '<' in remaining:
            raise ValueError('malformed url rule: %r' % rule)
        yield None, None, remaining

举例

我们可以直接调用parse_rule,来测试一下:

print tuple(parse_rule('/user/<name>'))
# 输出:((None, None, '/user/'), ('default', None, 'name'))

本文来自网易实践者社区,经作者王一兵授权发布。