Flask app.add_url_rule 装饰器错误
我在Flask的路由中有一堆装饰器,想把它们合并成一个(包括 @app.route
)。
我有一个这样的 @route
函数:
from functools import wraps
def route(route, method):
def decorator(f):
print 'decorator defined'
print 'defining route'
app.add_url_rule(route, methods=method, view_func=f)
print 'route defined'
@wraps(f)
def wrapper(*args, **kwargs):
print 'Hello'
# do stuff here such as authenticate, authorise, check request json/arguments etc.
# these will get passed along with the route and method arguments above.
return f(*args, **kwargs)
return wrapper
return decorator
还有一个示例路由:
@route('/status', ['GET'])
def status():
return Response('hi', content_type='text/plain')
这个路由是定义好了,但 wrapper()
从来没有被调用,这真是奇怪。当我把 app.add_url_rule
移到装饰器外面,放到文件的最后时,wrapper()
就会被调用;所以在Flask启动时会打印 decorator defined
,而当我访问 GET /status
路由时,Hello
也会如预期那样打印出来。
但是,当我把 app.add_url_rule
放回到上面的装饰器里时,decorator defined
在启动时会打印,但当我调用 GET /status
时却没有打印 Hello
,就好像 app.add_url_rule
以某种方式覆盖了我定义的 wrapper()
函数。
这是为什么呢?看起来 app.add_url_route
以一种奇怪或意想不到的方式劫持了我的函数。
我该怎么做才能在访问路由时调用 wrapper()
,同时又能在装饰器中定义 app.add_url_rule
呢?
1 个回答
2
你注册的是原始函数,而不是包装函数,给Flask用的。当路由匹配时,Flask会调用f
,而不是wrapper
,因为你注册的是这个原始函数。
要让Flask在路由匹配时调用wrapper
,你需要这样做:
def route(route, method):
def decorator(f):
print 'decorator defined'
print 'defining route'
@wraps(f)
def wrapper(*args, **kwargs):
print 'Hello'
# do stuff here such as authenticate, authorise, check request json/arguments etc.
# these will get passed along with the route and method arguments above.
return f(*args, **kwargs)
app.add_url_rule(route, methods=method, view_func=wrapper)
print 'route defined'
return wrapper
return decorator