Skip to content
This repository
Newer
Older
100644 224 lines (169 sloc) 9.19 kb
e71a5ff8 »
2011-05-27 Started work on new request dispatching. Unittests not yet updated
1 .. _request-context:
2
3 The Request Context
4 ===================
5
6 This document describes the behavior in Flask 0.7 which is mostly in line
7 with the old behavior but has some small, subtle differences.
8
d26af4fd »
2012-04-09 Fixed some smaller things in the docs
9 It is recommended that you read the :ref:`app-context` chapter first.
e71a5ff8 »
2011-05-27 Started work on new request dispatching. Unittests not yet updated
10
11 Diving into Context Locals
12 --------------------------
13
14 Say you have a utility function that returns the URL the user should be
15 redirected to. Imagine it would always redirect to the URL's ``next``
16 parameter or the HTTP referrer or the index page::
17
18 from flask import request, url_for
19
20 def redirect_url():
21 return request.args.get('next') or \
22 request.referrer or \
23 url_for('index')
24
25 As you can see, it accesses the request object. If you try to run this
26 from a plain Python shell, this is the exception you will see:
27
28 >>> redirect_url()
29 Traceback (most recent call last):
30 File "<stdin>", line 1, in <module>
31 AttributeError: 'NoneType' object has no attribute 'request'
32
33 That makes a lot of sense because we currently do not have a request we
34 could access. So we have to make a request and bind it to the current
35 context. The :attr:`~flask.Flask.test_request_context` method can create
36 us a :class:`~flask.ctx.RequestContext`:
37
38 >>> ctx = app.test_request_context('/?next=http://example.com/')
39
40 This context can be used in two ways. Either with the `with` statement
41 or by calling the :meth:`~flask.ctx.RequestContext.push` and
42 :meth:`~flask.ctx.RequestContext.pop` methods:
43
44 >>> ctx.push()
45
46 From that point onwards you can work with the request object:
47
48 >>> redirect_url()
49 u'http://example.com/'
50
51 Until you call `pop`:
52
53 >>> ctx.pop()
54
55 Because the request context is internally maintained as a stack you can
56 push and pop multiple times. This is very handy to implement things like
57 internal redirects.
58
59 For more information of how to utilize the request context from the
60 interactive Python shell, head over to the :ref:`shell` chapter.
61
62 How the Context Works
63 ---------------------
64
65 If you look into how the Flask WSGI application internally works, you will
66 find a piece of code that looks very much like this::
67
68 def wsgi_app(self, environ):
69 with self.request_context(environ):
70 try:
71 response = self.full_dispatch_request()
72 except Exception, e:
73 response = self.make_response(self.handle_exception(e))
74 return response(environ, start_response)
75
76 The method :meth:`~Flask.request_context` returns a new
77 :class:`~flask.ctx.RequestContext` object and uses it in combination with
78 the `with` statement to bind the context. Everything that is called from
79 the same thread from this point onwards until the end of the `with`
80 statement will have access to the request globals (:data:`flask.request`
81 and others).
82
83 The request context internally works like a stack: The topmost level on
84 the stack is the current active request.
85 :meth:`~flask.ctx.RequestContext.push` adds the context to the stack on
86 the very top, :meth:`~flask.ctx.RequestContext.pop` removes it from the
87 stack again. On popping the application's
88 :func:`~flask.Flask.teardown_request` functions are also executed.
89
9bed20c0 »
2012-04-09 Added documentation for appcontext and teardown handlers
90 Another thing of note is that the request context will automatically also
91 create an :ref:`application context <app-context>` when it's pushed and
92 there is no application context for that application so far.
93
e71a5ff8 »
2011-05-27 Started work on new request dispatching. Unittests not yet updated
94 .. _callbacks-and-errors:
95
96 Callbacks and Errors
97 --------------------
98
99 What happens if an error occurs in Flask during request processing? This
100 particular behavior changed in 0.7 because we wanted to make it easier to
101 understand what is actually happening. The new behavior is quite simple:
102
103 1. Before each request, :meth:`~flask.Flask.before_request` functions are
104 executed. If one of these functions return a response, the other
105 functions are no longer called. In any case however the return value
106 is treated as a replacement for the view's return value.
107
108 2. If the :meth:`~flask.Flask.before_request` functions did not return a
109 response, the regular request handling kicks in and the view function
110 that was matched has the chance to return a response.
111
112 3. The return value of the view is then converted into an actual response
113 object and handed over to the :meth:`~flask.Flask.after_request`
114 functions which have the chance to replace it or modify it in place.
115
116 4. At the end of the request the :meth:`~flask.Flask.teardown_request`
117 functions are executed. This always happens, even in case of an
d3ca5517 »
2011-08-25 Updated the docs and examples to non-failing teardown handlers
118 unhandled exception down the road or if a before-request handler was
119 not executed yet or at all (for example in test environments sometimes
120 you might want to not execute before-request callbacks).
e71a5ff8 »
2011-05-27 Started work on new request dispatching. Unittests not yet updated
121
122 Now what happens on errors? In production mode if an exception is not
123 caught, the 500 internal server handler is called. In development mode
124 however the exception is not further processed and bubbles up to the WSGI
125 server. That way things like the interactive debugger can provide helpful
126 debug information.
127
128 An important change in 0.7 is that the internal server error is now no
129 longer post processed by the after request callbacks and after request
130 callbacks are no longer guaranteed to be executed. This way the internal
131 dispatching code looks cleaner and is easier to customize and understand.
132
133 The new teardown functions are supposed to be used as a replacement for
134 things that absolutely need to happen at the end of request.
135
136 Teardown Callbacks
137 ------------------
138
139 The teardown callbacks are special callbacks in that they are executed at
5689ef36 »
2013-10-22 Fix typo s/at at/at a/
140 a different point. Strictly speaking they are independent of the actual
e71a5ff8 »
2011-05-27 Started work on new request dispatching. Unittests not yet updated
141 request handling as they are bound to the lifecycle of the
142 :class:`~flask.ctx.RequestContext` object. When the request context is
143 popped, the :meth:`~flask.Flask.teardown_request` functions are called.
144
145 This is important to know if the life of the request context is prolonged
e140bad3 »
2011-07-10 fixed typo
146 by using the test client in a with statement or when using the request
e71a5ff8 »
2011-05-27 Started work on new request dispatching. Unittests not yet updated
147 context from the command line::
148
149 with app.test_client() as client:
150 resp = client.get('/foo')
151 # the teardown functions are still not called at that point
152 # even though the response ended and you have the response
153 # object in your hand
154
155 # only when the code reaches this point the teardown functions
156 # are called. Alternatively the same thing happens if another
157 # request was triggered from the test client
158
159 It's easy to see the behavior from the command line:
160
161 >>> app = Flask(__name__)
162 >>> @app.teardown_request
20bf8edc »
2011-06-07 Rename teardown example to avoid confusion.
163 ... def teardown_request(exception=None):
164 ... print 'this runs after request'
165 ...
e71a5ff8 »
2011-05-27 Started work on new request dispatching. Unittests not yet updated
166 >>> ctx = app.test_request_context()
167 >>> ctx.push()
168 >>> ctx.pop()
20bf8edc »
2011-06-07 Rename teardown example to avoid confusion.
169 this runs after request
170 >>>
e71a5ff8 »
2011-05-27 Started work on new request dispatching. Unittests not yet updated
171
d3ca5517 »
2011-08-25 Updated the docs and examples to non-failing teardown handlers
172 Keep in mind that teardown callbacks are always executed, even if
173 before-request callbacks were not executed yet but an exception happened.
174 Certain parts of the test system might also temporarily create a request
175 context without calling the before-request handlers. Make sure to write
176 your teardown-request handlers in a way that they will never fail.
177
e71a5ff8 »
2011-05-27 Started work on new request dispatching. Unittests not yet updated
178 .. _notes-on-proxies:
179
180 Notes On Proxies
181 ----------------
182
183 Some of the objects provided by Flask are proxies to other objects. The
184 reason behind this is that these proxies are shared between threads and
185 they have to dispatch to the actual object bound to a thread behind the
186 scenes as necessary.
187
188 Most of the time you don't have to care about that, but there are some
189 exceptions where it is good to know that this object is an actual proxy:
190
191 - The proxy objects do not fake their inherited types, so if you want to
192 perform actual instance checks, you have to do that on the instance
193 that is being proxied (see `_get_current_object` below).
194 - if the object reference is important (so for example for sending
195 :ref:`signals`)
196
197 If you need to get access to the underlying object that is proxied, you
198 can use the :meth:`~werkzeug.local.LocalProxy._get_current_object` method::
199
200 app = current_app._get_current_object()
201 my_signal.send(app)
202
203 Context Preservation on Error
204 -----------------------------
205
206 If an error occurs or not, at the end of the request the request context
207 is popped and all data associated with it is destroyed. During
208 development however that can be problematic as you might want to have the
209 information around for a longer time in case an exception occurred. In
210 Flask 0.6 and earlier in debug mode, if an exception occurred, the
211 request context was not popped so that the interactive debugger can still
212 provide you with important information.
213
214 Starting with Flask 0.7 you have finer control over that behavior by
215 setting the ``PRESERVE_CONTEXT_ON_EXCEPTION`` configuration variable. By
216 default it's linked to the setting of ``DEBUG``. If the application is in
217 debug mode the context is preserved, in production mode it's not.
218
219 Do not force activate ``PRESERVE_CONTEXT_ON_EXCEPTION`` in production mode
220 as it will cause your application to leak memory on exceptions. However
221 it can be useful during development to get the same error preserving
222 behavior as in development mode when attempting to debug an error that
223 only occurs under production settings.
Something went wrong with that request. Please try again.