Signals¶
Flask allows you to act on events and customise behaviour using signals.
Signals require Blinker to be installed, though many app hooks don’t use signals, just a list of callables.
Signals vs Hooks¶
Flask signals use Blinker and are usually informational (e.g. you want to watch for errors and log them).
Flask hooks (usually spotted by being methods on blueprints or apps) don’t require Blinker and allow you to modify the request or response. These change the behaviour of the app (or blueprint).
Typically you want hooks for changing behaviour (e.g. authentication or error handling) and signals for recording events (e.g. logging).
Caveat¶
I got bitten by the difference between flask.request_finished and flask.got_request_exception, the former doesn’t fire when there is an error (HTTP 500) as Flask doesn’t hit that part of the code, while got_request_exception fires on all exceptions. I wound up putting two handlers in place.
Flask 0.9 Lifecycle¶
Flask 0.9 full_dispatch_request():
request_started.send(app) -> signal
rv = preprocess_request()
rv = [fn() for fn in before_request_funcs (@before_request)]
(rv = dispatch_request() calls actual view)
except: rv = handle_user_exception(e)
rv = [fn(e) for fn in error_handler_spec[e | status_code] (@errorhandler)]
(response = make_response(rv) uses response_class)
response = process_response(response)
response = [fn(response) for fn in after_request_funcs (@after_request)]
request_finished.send(app, response=response) -> signal
Flask 0.9 hooks to modify content:
@before_request (can give its own response, e.g. auth denied)
@errorhandler(e) (can work off exception type or status code, can set its own response)
@after_request(response) (can override the response)
Flask 0.9 signals:
request_started.send(app)
got_request_exception.send(app, exception=e)
request_finished.send(app, response=response)
request_tearing_down.send(app, exc=exc) (@teardown_request(exception) (always called at the end, possibly passed an exception)
Code¶
Signals let you change the behaviour of your app or blueprint
-
pythonie.blueprints.signals.
authenticate
()[source]¶ Performs authentication based on HTTP params
Looks for a password param.
-
pythonie.blueprints.signals.
handle_errors
(e)[source]¶ Ensure exceptions always return JSON errors
Note how this is registered with either an exception type or a HTTP code.
-
pythonie.blueprints.signals.
index
()[source]¶ A simple demo of authentication
To see in action go to http://building-webapps-with-flask.herokuapp.com/signals/?password=sekret
-
pythonie.blueprints.signals.
notjson
()[source]¶ A simple demo of very specific error handling
To see in action go to http://building-webapps-with-flask.herokuapp.com/signals/not.json?password=sekret
URLs¶
-
GET
/signals/not.json
¶ A simple demo of very specific error handling
To see in action go to http://building-webapps-with-flask.herokuapp.com/signals/not.json?password=sekret
-
GET
/signals/
¶ A simple demo of authentication
To see in action go to http://building-webapps-with-flask.herokuapp.com/signals/?password=sekret
-
GET
/
¶ To see this in action go to http://building-webapps-with-flask.herokuapp.com/