| 
									
										
										
										
											2011-05-28 02:10:53 +08:00
										 |  |  | .. _request-context:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The Request Context
 | 
					
						
							|  |  |  | ===================
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This document describes the behavior in Flask 0.7 which is mostly in line
 | 
					
						
							|  |  |  | with the old behavior but has some small, subtle differences.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | One of the design ideas behind Flask is that there are two different
 | 
					
						
							|  |  |  | “states” in which code is executed.  The application setup state in which
 | 
					
						
							|  |  |  | the application implicitly is on the module level.  It starts when the
 | 
					
						
							|  |  |  | :class:`Flask` object is instantiated, and it implicitly ends when the
 | 
					
						
							|  |  |  | first request comes in.  While the application is in this state a few
 | 
					
						
							|  |  |  | assumptions are true:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | -   the programmer can modify the application object safely.
 | 
					
						
							|  |  |  | -   no request handling happened so far
 | 
					
						
							|  |  |  | -   you have to have a reference to the application object in order to
 | 
					
						
							|  |  |  |     modify it, there is no magic proxy that can give you a reference to
 | 
					
						
							|  |  |  |     the application object you're currently creating or modifying.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | On the contrast, during request handling, a couple of other rules exist:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | -   while a request is active, the context local objects
 | 
					
						
							|  |  |  |     (:data:`flask.request` and others) point to the current request.
 | 
					
						
							|  |  |  | -   any code can get hold of these objects at any time.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The magic that makes this works is internally referred in Flask as the
 | 
					
						
							|  |  |  | “request context”.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Diving into Context Locals
 | 
					
						
							|  |  |  | --------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Say you have a utility function that returns the URL the user should be
 | 
					
						
							|  |  |  | redirected to.  Imagine it would always redirect to the URL's ``next``
 | 
					
						
							|  |  |  | parameter or the HTTP referrer or the index page::
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     from flask import request, url_for
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def redirect_url():
 | 
					
						
							|  |  |  |         return request.args.get('next') or \
 | 
					
						
							|  |  |  |                request.referrer or \
 | 
					
						
							|  |  |  |                url_for('index')
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | As you can see, it accesses the request object.  If you try to run this
 | 
					
						
							|  |  |  | from a plain Python shell, this is the exception you will see:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | >>> redirect_url()
 | 
					
						
							|  |  |  | Traceback (most recent call last):
 | 
					
						
							|  |  |  |   File "<stdin>", line 1, in <module>
 | 
					
						
							|  |  |  | AttributeError: 'NoneType' object has no attribute 'request'
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | That makes a lot of sense because we currently do not have a request we
 | 
					
						
							|  |  |  | could access.  So we have to make a request and bind it to the current
 | 
					
						
							|  |  |  | context.  The :attr:`~flask.Flask.test_request_context` method can create
 | 
					
						
							|  |  |  | us a :class:`~flask.ctx.RequestContext`:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | >>> ctx = app.test_request_context('/?next=http://example.com/')
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This context can be used in two ways.  Either with the `with` statement
 | 
					
						
							|  |  |  | or by calling the :meth:`~flask.ctx.RequestContext.push` and
 | 
					
						
							|  |  |  | :meth:`~flask.ctx.RequestContext.pop` methods:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | >>> ctx.push()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | From that point onwards you can work with the request object:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | >>> redirect_url()
 | 
					
						
							|  |  |  | u'http://example.com/'
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Until you call `pop`:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | >>> ctx.pop()
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Because the request context is internally maintained as a stack you can
 | 
					
						
							|  |  |  | push and pop multiple times.  This is very handy to implement things like
 | 
					
						
							|  |  |  | internal redirects.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | For more information of how to utilize the request context from the
 | 
					
						
							|  |  |  | interactive Python shell, head over to the :ref:`shell` chapter.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | How the Context Works
 | 
					
						
							|  |  |  | ---------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If you look into how the Flask WSGI application internally works, you will
 | 
					
						
							|  |  |  | find a piece of code that looks very much like this::
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def wsgi_app(self, environ):
 | 
					
						
							|  |  |  |         with self.request_context(environ):
 | 
					
						
							|  |  |  |             try:
 | 
					
						
							|  |  |  |                 response = self.full_dispatch_request()
 | 
					
						
							|  |  |  |             except Exception, e:
 | 
					
						
							|  |  |  |                 response = self.make_response(self.handle_exception(e))
 | 
					
						
							|  |  |  |             return response(environ, start_response)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The method :meth:`~Flask.request_context` returns a new
 | 
					
						
							|  |  |  | :class:`~flask.ctx.RequestContext` object and uses it in combination with
 | 
					
						
							|  |  |  | the `with` statement to bind the context.  Everything that is called from
 | 
					
						
							|  |  |  | the same thread from this point onwards until the end of the `with`
 | 
					
						
							|  |  |  | statement will have access to the request globals (:data:`flask.request`
 | 
					
						
							|  |  |  | and others).
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The request context internally works like a stack: The topmost level on
 | 
					
						
							|  |  |  | the stack is the current active request.
 | 
					
						
							|  |  |  | :meth:`~flask.ctx.RequestContext.push` adds the context to the stack on
 | 
					
						
							|  |  |  | the very top, :meth:`~flask.ctx.RequestContext.pop` removes it from the
 | 
					
						
							|  |  |  | stack again.  On popping the application's
 | 
					
						
							|  |  |  | :func:`~flask.Flask.teardown_request` functions are also executed.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .. _callbacks-and-errors:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Callbacks and Errors
 | 
					
						
							|  |  |  | --------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | What happens if an error occurs in Flask during request processing?  This
 | 
					
						
							|  |  |  | particular behavior changed in 0.7 because we wanted to make it easier to
 | 
					
						
							|  |  |  | understand what is actually happening.  The new behavior is quite simple:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 1.  Before each request, :meth:`~flask.Flask.before_request` functions are
 | 
					
						
							|  |  |  |     executed.  If one of these functions return a response, the other
 | 
					
						
							|  |  |  |     functions are no longer called.  In any case however the return value
 | 
					
						
							|  |  |  |     is treated as a replacement for the view's return value.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 2.  If the :meth:`~flask.Flask.before_request` functions did not return a
 | 
					
						
							|  |  |  |     response, the regular request handling kicks in and the view function
 | 
					
						
							|  |  |  |     that was matched has the chance to return a response.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 3.  The return value of the view is then converted into an actual response
 | 
					
						
							|  |  |  |     object and handed over to the :meth:`~flask.Flask.after_request`
 | 
					
						
							|  |  |  |     functions which have the chance to replace it or modify it in place.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 4.  At the end of the request the :meth:`~flask.Flask.teardown_request`
 | 
					
						
							|  |  |  |     functions are executed.  This always happens, even in case of an
 | 
					
						
							|  |  |  |     unhandled exception down the road.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Now what happens on errors?  In production mode if an exception is not
 | 
					
						
							|  |  |  | caught, the 500 internal server handler is called.  In development mode
 | 
					
						
							|  |  |  | however the exception is not further processed and bubbles up to the WSGI
 | 
					
						
							|  |  |  | server.  That way things like the interactive debugger can provide helpful
 | 
					
						
							|  |  |  | debug information.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | An important change in 0.7 is that the internal server error is now no
 | 
					
						
							|  |  |  | longer post processed by the after request callbacks and after request
 | 
					
						
							|  |  |  | callbacks are no longer guaranteed to be executed.  This way the internal
 | 
					
						
							|  |  |  | dispatching code looks cleaner and is easier to customize and understand.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The new teardown functions are supposed to be used as a replacement for
 | 
					
						
							|  |  |  | things that absolutely need to happen at the end of request.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Teardown Callbacks
 | 
					
						
							|  |  |  | ------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | The teardown callbacks are special callbacks in that they are executed at
 | 
					
						
							|  |  |  | at different point.  Strictly speaking they are independent of the actual
 | 
					
						
							|  |  |  | request handling as they are bound to the lifecycle of the
 | 
					
						
							|  |  |  | :class:`~flask.ctx.RequestContext` object.  When the request context is
 | 
					
						
							|  |  |  | popped, the :meth:`~flask.Flask.teardown_request` functions are called.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | This is important to know if the life of the request context is prolonged
 | 
					
						
							|  |  |  | by using the test client in a with statement of when using the request
 | 
					
						
							|  |  |  | context from the command line::
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     with app.test_client() as client:
 | 
					
						
							|  |  |  |         resp = client.get('/foo')
 | 
					
						
							|  |  |  |         # the teardown functions are still not called at that point
 | 
					
						
							|  |  |  |         # even though the response ended and you have the response
 | 
					
						
							|  |  |  |         # object in your hand
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     # only when the code reaches this point the teardown functions
 | 
					
						
							|  |  |  |     # are called.  Alternatively the same thing happens if another
 | 
					
						
							|  |  |  |     # request was triggered from the test client
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | It's easy to see the behavior from the command line:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | >>> app = Flask(__name__)
 | 
					
						
							|  |  |  | >>> @app.teardown_request
 | 
					
						
							| 
									
										
										
										
											2011-06-08 09:55:07 +08:00
										 |  |  | ... def teardown_request(exception=None):
 | 
					
						
							|  |  |  | ...     print 'this runs after request'
 | 
					
						
							|  |  |  | ...
 | 
					
						
							| 
									
										
										
										
											2011-05-28 02:10:53 +08:00
										 |  |  | >>> ctx = app.test_request_context()
 | 
					
						
							|  |  |  | >>> ctx.push()
 | 
					
						
							|  |  |  | >>> ctx.pop()
 | 
					
						
							| 
									
										
										
										
											2011-06-08 09:55:07 +08:00
										 |  |  | this runs after request
 | 
					
						
							|  |  |  | >>>
 | 
					
						
							| 
									
										
										
										
											2011-05-28 02:10:53 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | .. _notes-on-proxies:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Notes On Proxies
 | 
					
						
							|  |  |  | ----------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Some of the objects provided by Flask are proxies to other objects.  The
 | 
					
						
							|  |  |  | reason behind this is that these proxies are shared between threads and
 | 
					
						
							|  |  |  | they have to dispatch to the actual object bound to a thread behind the
 | 
					
						
							|  |  |  | scenes as necessary.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Most of the time you don't have to care about that, but there are some
 | 
					
						
							|  |  |  | exceptions where it is good to know that this object is an actual proxy:
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | -   The proxy objects do not fake their inherited types, so if you want to
 | 
					
						
							|  |  |  |     perform actual instance checks, you have to do that on the instance
 | 
					
						
							|  |  |  |     that is being proxied (see `_get_current_object` below).
 | 
					
						
							|  |  |  | -   if the object reference is important (so for example for sending
 | 
					
						
							|  |  |  |     :ref:`signals`)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If you need to get access to the underlying object that is proxied, you
 | 
					
						
							|  |  |  | can use the :meth:`~werkzeug.local.LocalProxy._get_current_object` method::
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     app = current_app._get_current_object()
 | 
					
						
							|  |  |  |     my_signal.send(app)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Context Preservation on Error
 | 
					
						
							|  |  |  | -----------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | If an error occurs or not, at the end of the request the request context
 | 
					
						
							|  |  |  | is popped and all data associated with it is destroyed.  During
 | 
					
						
							|  |  |  | development however that can be problematic as you might want to have the
 | 
					
						
							|  |  |  | information around for a longer time in case an exception occurred.  In
 | 
					
						
							|  |  |  | Flask 0.6 and earlier in debug mode, if an exception occurred, the
 | 
					
						
							|  |  |  | request context was not popped so that the interactive debugger can still
 | 
					
						
							|  |  |  | provide you with important information.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Starting with Flask 0.7 you have finer control over that behavior by
 | 
					
						
							|  |  |  | setting the ``PRESERVE_CONTEXT_ON_EXCEPTION`` configuration variable.  By
 | 
					
						
							|  |  |  | default it's linked to the setting of ``DEBUG``.  If the application is in
 | 
					
						
							|  |  |  | debug mode the context is preserved, in production mode it's not.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Do not force activate ``PRESERVE_CONTEXT_ON_EXCEPTION`` in production mode
 | 
					
						
							|  |  |  | as it will cause your application to leak memory on exceptions.  However
 | 
					
						
							|  |  |  | it can be useful during development to get the same error preserving
 | 
					
						
							|  |  |  | behavior as in development mode when attempting to debug an error that
 | 
					
						
							|  |  |  | only occurs under production settings.
 |