関数をラップして返す@Mark Hildreth の回答のバリエーションを次に示します。
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)
私が期待し期待したほど単純に機能しない理由は、Flask コンテキスト スタックとコールバックが適用される順序に関係しています。メソッド呼び出しのタイムラインを次に示します (削除されてからのいくつかのデバッグ ステートメントに基づく)。
$ python test-flask-app.py
# Application Launched
DECORATOR exclude_from_analytics
DECORATOR wrapper
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
# REQUEST: /
DECORATOR app.before_request: analytics_view
> Should skip analytics on /: False
ENDPOINT no_skip
127.0.0.1 - - [14/May/2016 16:10:39] "GET / HTTP/1.1" 200 -
# REQUEST: /skip
DECORATOR app.before_request: analytics_view
> Should skip analytics on /skip: True
DECORATOR wrapped
ENDPOINT skip
127.0.0.1 - - [14/May/2016 16:12:46] "GET /skip HTTP/1.1" 200 -
g.skip_analytics
関数内から設定することをお勧めしwrapped
ます。しかし、それはフックの後まで呼び出されないため、Markのanalytics_view
@app.before_request
例に従い、起動時にのみ呼び出されるアプリケーション( requestではなく) コンテキストを_skip_analytics
呼び出しているエンドポイント メソッドに attrを設定する必要がありました。
flask.g
アプリのコンテキストの詳細については、このStackOverflow answerを参照してください。