I have a bunch of decorators in my Flask routes that I am trying to condense into one (including @app.route
).
I have the following @route
function:
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
and a sample route:
@route('/status', ['GET'])
def status():
return Response('hi', content_type='text/plain')
The route is getting defined, but wrapper()
never gets called, which is really odd. When I move app.add_url_rule
outside of the decorator to the end of the file, then wrapper()
gets called; so decorator defined
statement prints on Flask startup, and Hello
prints when I hit the GET /status
route as expected.
However, when I put app.add_url_rule
back into the decorator as shown above, decorator defined
prints on startup but when I call GET /status
, it does not print Hello
as if app.add_url_rule
overrides the wrapper()
function that I defined somehow.
Why does this happen? It looks like app.add_url_route
hijacks my function in some odd/unexpected way.
How can I get wrapper()
to be called once the route is hit, while defining app.add_url_rule
in the decorator?
You registered the original function, not the wrapper, with Flask. Whenever the route matches, Flask calls f
, not wrapper
, because that's what you registered for the route.
Tell Flask to call wrapper
when the route matches, instead:
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