Here's a @Mark Hildreth answer option that completes and returns a function:
from functools import wraps from flask import Flask, request, g app = Flask(__name__) def exclude_from_analytics(*args, **kw): def wrapper(endpoint_method): endpoint_method._skip_analytics = True @wraps(endpoint_method) def wrapped(*endpoint_args, **endpoint_kw): # This is what I want I want to do. Will not work. #g.skip_analytics = getattr(endpoint_method, '_skip_analytics', False) return endpoint_method(*endpoint_args, **endpoint_kw) return wrapped return wrapper @app.route('/') def no_skip(): return 'Skip analytics? %s' % (g.skip_analytics) @app.route('/skip') @exclude_from_analytics() def skip(): return 'Skip analytics? %s' % (g.skip_analytics) @app.before_request def analytics_view(*args, **kwargs): if request.endpoint in app.view_functions: view_func = app.view_functions[request.endpoint] g.skip_analytics = hasattr(view_func, '_skip_analytics') print 'Should skip analytics on {0}: {1}'.format(request.path, g.skip_analytics) app.run(debug=True)
The reason this works is not as simple as I expected, and was hoping to do something with the Flask context stack and the order in which callbacks apply. The following is a graph of method calls (based on some debug instructions from the moment of deletion):
$ python test-flask-app.py
I would prefer to set g.skip_analytics from the wrapped function. But since this is not called until there is an analytics_view @app.before_request , I had to follow Mark's example and set _skip_analytics attr in the endpoint method loaded in what I call the application (as opposed to the request ), which is called only at startup.
For more information about flask.g and the application context, see https://stackoverflow.com/a/312618/
klenwell
source share