Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 111 lines (79 sloc) 3.851 kB
ef0dc18 @mitsuhiko Added interactive Python docs, fixed part style.
authored
1 Working with the Shell
2 ======================
3
ce6e4cb @mitsuhiko 0.5 is 0.3 now, why skip numbers?
authored
4 .. versionadded:: 0.3
ef0dc18 @mitsuhiko Added interactive Python docs, fixed part style.
authored
5
6 One of the reasons everybody loves Python is the interactive shell. It
7 basically allows you to execute Python commands in real time and
8 immediately get results back. Flask itself does not come with an
9 interactive shell, because it does not require any specific setup upfront,
10 just import your application and start playing around.
11
12 There are however some handy helpers to make playing around in the shell a
13 more pleasant experience. The main issue with interactive console
14 sessions is that you're not triggering a request like a browser does which
15 means that :data:`~flask.g`, :data:`~flask.request` and others are not
16 available. But the code you want to test might depend on them, so what
17 can you do?
18
19 This is where some helper functions come in handy. Keep in mind however
20 that these functions are not only there for interactive shell usage, but
21 also for unittesting and other situations that require a faked request
22 context.
23
24 Diving into Context Locals
25 --------------------------
26
27 Say you have a utility function that returns the URL the user should be
28 redirected to. Imagine it would always redirect to the URL's ``next``
29 parameter or the HTTP referrer or the index page::
30
31 from flask import request, url_for
32
33 def redirect_url():
34 return request.args.get('next') or \
35 request.referrer or \
36 url_for('index')
37
38 As you can see, it accesses the request object. If you try to run this
39 from a plain Python shell, this is the exception you will see:
40
41 >>> redirect_url()
42 Traceback (most recent call last):
43 File "<stdin>", line 1, in <module>
44 AttributeError: 'NoneType' object has no attribute 'request'
45
46 That makes a lot of sense because we currently do not have a request we
47 could access. So we have to make a request and bind it to the current
48 context. The :attr:`~flask.Flask.test_request_context` method can create
49 us a request context:
50
51 >>> ctx = app.test_request_context('/?next=http://example.com/')
52
53 This context can be used in two ways. Either with the `with` statement
54 (which unfortunately is not very handy for shell sessions). The
55 alternative way is to call the `push` and `pop` methods:
56
57 >>> ctx.push()
58
59 From that point onwards you can work with the request object:
60
61 >>> redirect_url()
62 u'http://example.com/'
63
64 Until you call `pop`:
65
66 >>> ctx.pop()
67 >>> redirect_url()
68 Traceback (most recent call last):
69 File "<stdin>", line 1, in <module>
70 AttributeError: 'NoneType' object has no attribute 'request'
71
72
73 Firing Before/After Request
74 ---------------------------
75
76 By just creating a request context, you still don't have run the code that
77 is normally run before a request. This probably results in your database
78 being unavailable, the current user not being stored on the
79 :data:`~flask.g` object etc.
80
81 This however can easily be done yourself. Just call
82 :meth:`~flask.Flask.preprocess_request`:
83
84 >>> ctx = app.test_request_context()
85 >>> ctx.push()
86 >>> app.preprocess_request()
87
88 Keep in mind that the :meth:`~flask.Flask.preprocess_request` function
89 might return a response object, in that case just ignore it.
90
91 To shutdown a request, you need to trick a bit before the after request
92 functions (triggered by :meth:`~flask.Flask.process_response`) operate on
93 a response object:
94
95 >>> app.process_response(app.response_class())
96 <Response 0 bytes [200 OK]>
97 >>> ctx.pop()
98
99
100 Further Improving the Shell Experience
101 --------------------------------------
102
103 If you like the idea of experimenting in a shell, create yourself a module
104 with stuff you want to star import into your interactive session. There
105 you could also define some more helper methods for common things such as
106 initializing the database, dropping tables etc.
107
108 Just put them into a module (like `shelltools` and import from there):
109
110 >>> from shelltools import *
Something went wrong with that request. Please try again.