forked from orbit-oss/flask
Merge pull request #2279 from davidism/docs-after_this_request
Clean up deferred callback doc
This commit is contained in:
commit
716edfdb29
1 changed files with 23 additions and 51 deletions
|
|
@ -3,71 +3,43 @@
|
||||||
Deferred Request Callbacks
|
Deferred Request Callbacks
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
One of the design principles of Flask is that response objects are created
|
One of the design principles of Flask is that response objects are created and
|
||||||
and passed down a chain of potential callbacks that can modify them or
|
passed down a chain of potential callbacks that can modify them or replace
|
||||||
replace them. When the request handling starts, there is no response
|
them. When the request handling starts, there is no response object yet. It is
|
||||||
object yet. It is created as necessary either by a view function or by
|
created as necessary either by a view function or by some other component in
|
||||||
some other component in the system.
|
the system.
|
||||||
|
|
||||||
But what happens if you want to modify the response at a point where the
|
What happens if you want to modify the response at a point where the response
|
||||||
response does not exist yet? A common example for that would be a
|
does not exist yet? A common example for that would be a
|
||||||
before-request function that wants to set a cookie on the response object.
|
:meth:`~flask.Flask.before_request` callback that wants to set a cookie on the
|
||||||
|
response object.
|
||||||
|
|
||||||
One way is to avoid the situation. Very often that is possible. For
|
One way is to avoid the situation. Very often that is possible. For instance
|
||||||
instance you can try to move that logic into an after-request callback
|
you can try to move that logic into a :meth:`~flask.Flask.after_request`
|
||||||
instead. Sometimes however moving that code there is just not a very
|
callback instead. However, sometimes moving code there makes it more
|
||||||
pleasant experience or makes code look very awkward.
|
more complicated or awkward to reason about.
|
||||||
|
|
||||||
As an alternative possibility you can attach a bunch of callback functions
|
As an alternative, you can use :func:`~flask.after_this_request` to register
|
||||||
to the :data:`~flask.g` object and call them at the end of the request.
|
callbacks that will execute after only the current request. This way you can
|
||||||
This way you can defer code execution from anywhere in the application.
|
defer code execution from anywhere in the application, based on the current
|
||||||
|
request.
|
||||||
|
|
||||||
The Decorator
|
|
||||||
-------------
|
|
||||||
|
|
||||||
The following decorator is the key. It registers a function on a list on
|
|
||||||
the :data:`~flask.g` object::
|
|
||||||
|
|
||||||
from flask import g
|
|
||||||
|
|
||||||
def after_this_request(f):
|
|
||||||
if not hasattr(g, 'after_request_callbacks'):
|
|
||||||
g.after_request_callbacks = []
|
|
||||||
g.after_request_callbacks.append(f)
|
|
||||||
return f
|
|
||||||
|
|
||||||
|
|
||||||
Calling the Deferred
|
|
||||||
--------------------
|
|
||||||
|
|
||||||
Now you can use the `after_this_request` decorator to mark a function to
|
|
||||||
be called at the end of the request. But we still need to call them. For
|
|
||||||
this the following function needs to be registered as
|
|
||||||
:meth:`~flask.Flask.after_request` callback::
|
|
||||||
|
|
||||||
@app.after_request
|
|
||||||
def call_after_request_callbacks(response):
|
|
||||||
for callback in getattr(g, 'after_request_callbacks', ()):
|
|
||||||
callback(response)
|
|
||||||
return response
|
|
||||||
|
|
||||||
|
|
||||||
A Practical Example
|
|
||||||
-------------------
|
|
||||||
|
|
||||||
At any time during a request, we can register a function to be called at the
|
At any time during a request, we can register a function to be called at the
|
||||||
end of the request. For example you can remember the current language of the
|
end of the request. For example you can remember the current language of the
|
||||||
user in a cookie in the before-request function::
|
user in a cookie in a :meth:`~flask.Flask.before_request` callback::
|
||||||
|
|
||||||
from flask import request, after_this_request
|
from flask import request, after_this_request
|
||||||
|
|
||||||
@app.before_request
|
@app.before_request
|
||||||
def detect_user_language():
|
def detect_user_language():
|
||||||
language = request.cookies.get('user_lang')
|
language = request.cookies.get('user_lang')
|
||||||
|
|
||||||
if language is None:
|
if language is None:
|
||||||
language = guess_language_from_request()
|
language = guess_language_from_request()
|
||||||
|
|
||||||
|
# when the response exists, set a cookie with the language
|
||||||
@after_this_request
|
@after_this_request
|
||||||
def remember_language(response):
|
def remember_language(response):
|
||||||
response.set_cookie('user_lang', language)
|
response.set_cookie('user_lang', language)
|
||||||
|
|
||||||
g.language = language
|
g.language = language
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue