在使用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'))
本文来自网易实践者社区,经作者王一兵授权发布。