从代码开始
先来看一段代码
from flask import Flask, g, request
from functools import wraps
app = Flask(__name__)
def set_g(f):
@wraps(f)
def decorator(*args, **kwargs):
g.auth = 'zadmin'
g.scope = 5
g.num = 0
return f(*args, **kwargs)
return decorator
def check_auth(f):
@wraps(f)
def decorator(*args, **kwargs):
auth = g.auth
if auth != "admin":
print "Failed in auth"
g.num = 20
return f(*args, **kwargs)
return decorator
def check_scope(f):
#@wraps(f)
def decorator(*args, **kwargs):
''' This check scope docker string '''
scope = g.scope
if scope not in [1, 2, 3]:
print "Failed in scope"
g.num = 10
return f(*args, **kwargs)
return decorator
@app.route('/test')
@set_g
@check_auth
@check_scope
def test():
''' This is function test'''
print request.path
print g.auth, g.scope
print "g.num:{}".format(g.num)
print test.__doc__
return "test"
app.run(debug=True)
如果我访问这个 API 会在 terminal 打印什么呢?
Failed in auth
Failed in scope
/test
zadmin 5
g.num:10
This check scope docker string
装饰器会在下面的 blog 中专门说一下
这一篇只说 flask 的 route
从结果来推断,访问 API 之后函数的执行顺序是这样的:
这一篇只说 flask 的 route
从结果来推断,访问 API 之后函数的执行顺序是这样的:
app.route()=>set_g()=>check_auth()=>chek_scope()=>test()
flask 中的 route 到底做了什么
route
@setupmethod
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 是一个装饰器,负责将 URL 与 OPTION 传到 add_url_rule 这个函数中
这样的代码会更美观
这样的代码会更美观
add_url_rule
def add_url_rule(self, rule, endpoint=None, view_func=None, provide_automatic_options=None, **options):
if endpoint is None:
endpoint = _endpoint_from_view_func(view_func)
options['endpoint'] = endpoint
methods = options.pop('methods', None)
if methods is None:
methods = getattr(view_func, 'methods', None) or ('GET',)
if isinstance(methods, string_types):
raise TypeError('Allowed methods have to be iterables of strings, '
'for example: @app.route(..., methods=["POST"])')
methods = set(item.upper() for item in methods)
required_methods = set(getattr(view_func, 'required_methods', ()))
if provide_automatic_options is None:
provide_automatic_options = getattr(view_func,
'provide_automatic_options', None)
if provide_automatic_options is None:
if 'OPTIONS' not in methods:
provide_automatic_options = True
required_methods.add('OPTIONS')
else:
provide_automatic_options = False
methods |= required_methods
rule = self.url_rule_class(rule, methods=methods, **options)
rule.provide_automatic_options = provide_automatic_options
self.url_map.add(rule)
if view_func is not None:
old_func = self.view_functions.get(endpoint)
if old_func is not None and old_func != view_func:
raise AssertionError('View function mapping is overwriting an '
'existing endpoint function: %s' % endpoint)
self.view_functions[endpoint] = view_func
add_url_rule 处理传来的参数然后将符合规则的 url 与 method 生成一个 rule 对象
再将 rule 加到 Map() 对象中存储起来
这也是 flask 中 url 与 method 全局唯一的保证
再将 rule 加到 Map() 对象中存储起来
这也是 flask 中 url 与 method 全局唯一的保证
这样看来
完整的过程是这样的:
route()=>add_url_rule()=>RULE()=>url_map.add()=>set_g()=>check_auth()=>chek_scope()=>test()
完整的过程是这样的:
route()=>add_url_rule()=>RULE()=>url_map.add()=>set_g()=>check_auth()=>chek_scope()=>test()
评论
发表评论