mirror of https://github.com/pallets/flask.git
Added after_this_request decorator.
This commit is contained in:
parent
dbfd406a21
commit
086348e2f2
1
CHANGES
1
CHANGES
|
@ -70,6 +70,7 @@ Relase date to be decided, codename to be chosen.
|
||||||
be used on creation of the :data:`~flask.g` instance of each request.
|
be used on creation of the :data:`~flask.g` instance of each request.
|
||||||
- Added `required_methods` attribute to view functions to force-add methods
|
- Added `required_methods` attribute to view functions to force-add methods
|
||||||
on registration.
|
on registration.
|
||||||
|
- Added :func:`flask.after_this_request`.
|
||||||
|
|
||||||
Version 0.8.1
|
Version 0.8.1
|
||||||
-------------
|
-------------
|
||||||
|
|
|
@ -289,6 +289,8 @@ Useful Functions and Classes
|
||||||
|
|
||||||
.. autofunction:: make_response
|
.. autofunction:: make_response
|
||||||
|
|
||||||
|
.. autofunction:: after_this_request
|
||||||
|
|
||||||
.. autofunction:: send_file
|
.. autofunction:: send_file
|
||||||
|
|
||||||
.. autofunction:: send_from_directory
|
.. autofunction:: send_from_directory
|
||||||
|
|
|
@ -25,7 +25,8 @@ from .helpers import url_for, jsonify, json_available, flash, \
|
||||||
get_template_attribute, make_response, safe_join
|
get_template_attribute, make_response, safe_join
|
||||||
from .globals import current_app, g, request, session, _request_ctx_stack, \
|
from .globals import current_app, g, request, session, _request_ctx_stack, \
|
||||||
_app_ctx_stack
|
_app_ctx_stack
|
||||||
from .ctx import has_request_context, has_app_context
|
from .ctx import has_request_context, has_app_context, \
|
||||||
|
after_this_request
|
||||||
from .module import Module
|
from .module import Module
|
||||||
from .blueprints import Blueprint
|
from .blueprints import Blueprint
|
||||||
from .templating import render_template, render_template_string
|
from .templating import render_template, render_template_string
|
||||||
|
|
|
@ -1555,7 +1555,7 @@ class Flask(_PackageBoundObject):
|
||||||
"""
|
"""
|
||||||
ctx = _request_ctx_stack.top
|
ctx = _request_ctx_stack.top
|
||||||
bp = ctx.request.blueprint
|
bp = ctx.request.blueprint
|
||||||
funcs = ()
|
funcs = ctx._after_request_functions
|
||||||
if bp is not None and bp in self.after_request_funcs:
|
if bp is not None and bp in self.after_request_funcs:
|
||||||
funcs = reversed(self.after_request_funcs[bp])
|
funcs = reversed(self.after_request_funcs[bp])
|
||||||
if None in self.after_request_funcs:
|
if None in self.after_request_funcs:
|
||||||
|
|
30
flask/ctx.py
30
flask/ctx.py
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
from functools import partial
|
||||||
from werkzeug.exceptions import HTTPException
|
from werkzeug.exceptions import HTTPException
|
||||||
|
|
||||||
from .globals import _request_ctx_stack, _app_ctx_stack
|
from .globals import _request_ctx_stack, _app_ctx_stack
|
||||||
|
@ -30,6 +31,31 @@ def _push_app_if_necessary(app):
|
||||||
return ctx
|
return ctx
|
||||||
|
|
||||||
|
|
||||||
|
def after_this_request(f):
|
||||||
|
"""Executes a function after this request. This is useful to modify
|
||||||
|
response objects. The function is passed the response object and has
|
||||||
|
to return the same or a new one.
|
||||||
|
|
||||||
|
Example::
|
||||||
|
|
||||||
|
@app.route('/')
|
||||||
|
def index():
|
||||||
|
@after_this_request
|
||||||
|
def add_header():
|
||||||
|
response.headers['X-Foo'] = 'Parachute'
|
||||||
|
return response
|
||||||
|
return 'Hello World!'
|
||||||
|
|
||||||
|
This is more useful if a function other than the view function wants to
|
||||||
|
modify a response. For instance think of a decorator that wants to add
|
||||||
|
some headers without converting the return value into a response object.
|
||||||
|
|
||||||
|
.. versionadded:: 0.9
|
||||||
|
"""
|
||||||
|
_request_ctx_stack.top._after_request_functions.append(f)
|
||||||
|
return f
|
||||||
|
|
||||||
|
|
||||||
def has_request_context():
|
def has_request_context():
|
||||||
"""If you have code that wants to test if a request context is there or
|
"""If you have code that wants to test if a request context is there or
|
||||||
not this function can be used. For instance, you may want to take advantage
|
not this function can be used. For instance, you may want to take advantage
|
||||||
|
@ -153,6 +179,10 @@ class RequestContext(object):
|
||||||
# context, it will be stored there
|
# context, it will be stored there
|
||||||
self._pushed_application_context = None
|
self._pushed_application_context = None
|
||||||
|
|
||||||
|
# Functions that should be executed after the request on the response
|
||||||
|
# object. These will even be called in case of an error.
|
||||||
|
self._after_request_functions = []
|
||||||
|
|
||||||
self.match_request()
|
self.match_request()
|
||||||
|
|
||||||
# XXX: Support for deprecated functionality. This is going away with
|
# XXX: Support for deprecated functionality. This is going away with
|
||||||
|
|
|
@ -411,6 +411,21 @@ class BasicFunctionalityTestCase(FlaskTestCase):
|
||||||
self.assert_('after' in evts)
|
self.assert_('after' in evts)
|
||||||
self.assert_equal(rv, 'request|after')
|
self.assert_equal(rv, 'request|after')
|
||||||
|
|
||||||
|
def test_after_request_processing(self):
|
||||||
|
app = flask.Flask(__name__)
|
||||||
|
app.testing = True
|
||||||
|
@app.route('/')
|
||||||
|
def index():
|
||||||
|
@flask.after_this_request
|
||||||
|
def foo(response):
|
||||||
|
response.headers['X-Foo'] = 'a header'
|
||||||
|
return response
|
||||||
|
return 'Test'
|
||||||
|
c = app.test_client()
|
||||||
|
resp = c.get('/')
|
||||||
|
self.assertEqual(resp.status_code, 200)
|
||||||
|
self.assertEqual(resp.headers['X-Foo'], 'a header')
|
||||||
|
|
||||||
def test_teardown_request_handler(self):
|
def test_teardown_request_handler(self):
|
||||||
called = []
|
called = []
|
||||||
app = flask.Flask(__name__)
|
app = flask.Flask(__name__)
|
||||||
|
|
Loading…
Reference in New Issue