flask路由
在使用flask时,我们设置路由的方式通常为:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return '1'
@app.route('/test')
def test():
return '2'
if __name__ == '__main__':
print(app.url_map)
问题来了, 我们并没有执行定义的函数,那么app.route()
方法是如何将我们的url和视图函数象关联并打印出url_map的呢?
route源码
def route(self, rule, **options):
def decorator(f):
endpoint = options.pop('endpoint', None)
self.add_url_rule(rule, endpoint, f, **options)
return f
return decorator
从源码可以发现,route的本质是一个装饰器,再route方法被触发后,进一步调用add_url_rule
来注册我们设定的url。
装饰器
在开始的代码中,我们并没有调用相关的视图函数,如index()
, 那么装饰器为什么还会被触发呢?
装饰器的作用大家应该都很清楚: 在不改变原有代码结构的基础上对函数进行一次封装,添加特定的功能。来看一个例子:
import time
def log(f):
def decorator():
t1 = time.time()
f()
t2 = time.time()
print('time: {}'.format(t2-t1))
return decorator
@log
def test():
time.sleep(2)
print('test')
if __name__ == '__main__':
test()
'''
结果:
test
time: 2.0009994506835938
'''
这个例子很常见,功能是在函数执行后打印该函数的执行时间。其实,在代码执行到@log时,python执行了下面一句代码: test = log(test)
这句代码返回decorator函数。让我们验证一下:
import time
def log(f):
def decorator():
t1 = time.time()
f()
t2 = time.time()
print('time: {}'.format(t2-t1))
print('log....')
return decorator
@log
def test():
time.sleep(2)
print('test')
if __name__ == '__main__':
pass
'''
结果:
log....
'''
明白了这一点,回到开始时的route方法:
@app.route('/')
def index():
return '1'
这段代码发生了什么?其实,它的调用过程为:index = app.route('/')(index)
route函数接收rule和关键字参数**options, rule的值为‘/’,执行后返回decorator,decorator接收一个参数f,值为index。route函数通过调用add_url_rule
方法将Rule类的实例,加入到url_map
中去。
网友评论