~justin-fathomdb/nova/justinsb-openstack-api-volumes

« back to all changes in this revision

Viewing changes to vendor/Twisted-10.0.0/doc/web/howto/web-in-60/session-store.html

  • Committer: Jesse Andrews
  • Date: 2010-05-28 06:05:26 UTC
  • Revision ID: git-v1:bf6e6e718cdc7488e2da87b21e258ccc065fe499
initial commit

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE html  PUBLIC '-//W3C//DTD XHTML 1.0 Transitional//EN'  'http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd'><html lang="en" xmlns="http://www.w3.org/1999/xhtml">
 
2
  <head>
 
3
<title>Twisted Documentation: Storing Objects in the Session</title>
 
4
<link href="../stylesheet.css" rel="stylesheet" type="text/css"/>
 
5
  </head>
 
6
 
 
7
  <body bgcolor="white">
 
8
    <h1 class="title">Storing Objects in the Session</h1>
 
9
    <div class="toc"><ol/></div>
 
10
    <div class="content">
 
11
<span/>
 
12
 
 
13
<p>This example shows you how you can persist objects across requests in the
 
14
session object.</p>
 
15
 
 
16
<p>As was discussed <a href="session-basics.html" shape="rect">previously</a>, instances
 
17
of <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.web.server.Session.html" title="twisted.web.server.Session">Session</a></code> last as long as
 
18
the notional session itself does. Each time <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.web.server.Request.getSession.html" title="twisted.web.server.Request.getSession">Request.getSession</a></code> is called, if the session
 
19
for the request is still active, then the same <code>Session</code> instance is
 
20
returned as was returned previously. Because of this, <code>Session</code>
 
21
instances can be used to keep other objects around for as long as the session
 
22
exists.</p>
 
23
 
 
24
<p>It's easier to demonstrate how this works than explain it, so here's an
 
25
example:</p>
 
26
 
 
27
<pre class="shell" xml:space="preserve">
 
28
&gt;&gt;&gt; from zope.interface import Interface, Attribute, implements
 
29
&gt;&gt;&gt; from twisted.python.components import registerAdapter
 
30
&gt;&gt;&gt; from twisted.web.server import Session
 
31
&gt;&gt;&gt; class ICounter(Interface):
 
32
...     value = Attribute(&quot;An int value which counts up once per page view.&quot;)
 
33
...
 
34
&gt;&gt;&gt; class Counter(object):
 
35
...     implements(ICounter)
 
36
...     def __init__(self, session):
 
37
...         self.value = 0
 
38
...
 
39
&gt;&gt;&gt; registerAdapter(Counter, Session, ICounter)
 
40
&gt;&gt;&gt; ses = Session(None, None)
 
41
&gt;&gt;&gt; data = ICounter(ses)
 
42
&gt;&gt;&gt; print data
 
43
&lt;__main__.Counter object at 0x8d535ec&gt;
 
44
&gt;&gt;&gt; print data is ICounter(ses)
 
45
True
 
46
&gt;&gt;&gt;
 
47
</pre>
 
48
 
 
49
<p><i>What?</i>, I hear you say.</p>
 
50
 
 
51
<p>What's shown in this example is the interface and adaption-based API which
 
52
<code>Session</code> exposes for persisting state. There are several critical
 
53
pieces interacting here:</p>
 
54
 
 
55
<ul>
 
56
  <li><code>ICounter</code> is an interface which serves several purposes. Like
 
57
    all interfaces, it documents the API of some class of objects (in this case,
 
58
    just the <code>value</code> attribute). It also serves as a key into what is
 
59
    basically a dictionary within the session object: the interface is used to
 
60
    store or retrieve a value on the session (the <code>Counter</code> instance,
 
61
    in this case).</li>
 
62
  <li><code>Counter</code> is the class which actually holds the session data in
 
63
    this example. It implements <code>ICounter</code> (again, mostly for
 
64
    documentation purposes). It also has a <code>value</code> attribute, as the
 
65
    interface declared.</li>
 
66
  <li>The <code class="API"><a href="http://twistedmatrix.com/documents/10.0.0/api/twisted.python.components.registerAdapter.html" title="twisted.python.components.registerAdapter">registerAdapter</a></code> call sets up the
 
67
    relationship between its three arguments so that adaption will do what we
 
68
    want in this case.</li>
 
69
  <li>Adaption is performed by the expression <code>ICounter(ses)</code>. This
 
70
    is read as <i>adapt <code>ses</code> to <code>ICounter</code></i>. Because
 
71
    of the <code>registerAdapter</code> call, it is roughly equivalent
 
72
    to <code>Counter(ses)</code>. However (because of certain
 
73
    things <code>Session</code> does), it also saves the <code>Counter</code>
 
74
    instance created so that it will be returned the next time this adaption is
 
75
    done. This is why the last statement produces <code>True</code>.</li>
 
76
</ul>
 
77
 
 
78
<p>If you're still not clear on some of the details there, don't worry about it
 
79
and just remember this: <code>ICounter(ses)</code> gives you an object you can
 
80
persist state on. It can be as much or as little state as you want, and you can
 
81
use as few or as many different <code>Interface</code> classes as you want on a
 
82
single <code>Session</code> instance.</p>
 
83
 
 
84
<p>With those conceptual dependencies out of the way, it's a very short step to
 
85
actually getting persistent state into a Twisted Web application. Here's an
 
86
example which implements a simple counter, re-using the definitions from the
 
87
example above:</p>
 
88
 
 
89
<pre class="python"><p class="py-linenumber">1
 
90
2
 
91
3
 
92
4
 
93
5
 
94
6
 
95
7
 
96
8
 
97
</p><span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">web</span>.<span class="py-src-variable">resource</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Resource</span>
 
98
 
 
99
<span class="py-src-keyword">class</span> <span class="py-src-identifier">CounterResource</span>(<span class="py-src-parameter">Resource</span>):
 
100
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">render_GET</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">request</span>):
 
101
        <span class="py-src-variable">session</span> = <span class="py-src-variable">request</span>.<span class="py-src-variable">getSession</span>()
 
102
        <span class="py-src-variable">counter</span> = <span class="py-src-variable">ICounter</span>(<span class="py-src-variable">session</span>)
 
103
        <span class="py-src-variable">counter</span>.<span class="py-src-variable">value</span> += <span class="py-src-number">1</span>
 
104
        <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;Visit #%d for you!&quot;</span> % (<span class="py-src-variable">counter</span>.<span class="py-src-variable">value</span>,)
 
105
</pre>
 
106
 
 
107
<p>Pretty simple from this side, eh? All this does is
 
108
use <code>Request.getSession</code> and the adaption from above, plus some
 
109
integer math to give you a session-based visit counter.</p>
 
110
 
 
111
<p>Here's the complete source for an <a href="rpy-scripts.html" shape="rect">rpy script</a>
 
112
based on this example:</p>
 
113
 
 
114
<pre class="python"><p class="py-linenumber"> 1
 
115
 2
 
116
 3
 
117
 4
 
118
 5
 
119
 6
 
120
 7
 
121
 8
 
122
 9
 
123
10
 
124
11
 
125
12
 
126
13
 
127
14
 
128
15
 
129
16
 
130
17
 
131
18
 
132
19
 
133
20
 
134
21
 
135
22
 
136
23
 
137
24
 
138
25
 
139
</p><span class="py-src-variable">cache</span>()
 
140
 
 
141
<span class="py-src-keyword">from</span> <span class="py-src-variable">zope</span>.<span class="py-src-variable">interface</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Interface</span>, <span class="py-src-variable">Attribute</span>, <span class="py-src-variable">implements</span>
 
142
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">python</span>.<span class="py-src-variable">components</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">registerAdapter</span>
 
143
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">web</span>.<span class="py-src-variable">server</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Session</span>
 
144
<span class="py-src-keyword">from</span> <span class="py-src-variable">twisted</span>.<span class="py-src-variable">web</span>.<span class="py-src-variable">resource</span> <span class="py-src-keyword">import</span> <span class="py-src-variable">Resource</span>
 
145
 
 
146
<span class="py-src-keyword">class</span> <span class="py-src-identifier">ICounter</span>(<span class="py-src-parameter">Interface</span>):
 
147
    <span class="py-src-variable">value</span> = <span class="py-src-variable">Attribute</span>(<span class="py-src-string">&quot;An int value which counts up once per page view.&quot;</span>)
 
148
 
 
149
<span class="py-src-keyword">class</span> <span class="py-src-identifier">Counter</span>(<span class="py-src-parameter">object</span>):
 
150
    <span class="py-src-variable">implements</span>(<span class="py-src-variable">ICounter</span>)
 
151
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">__init__</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">session</span>):
 
152
        <span class="py-src-variable">self</span>.<span class="py-src-variable">value</span> = <span class="py-src-number">0</span>
 
153
 
 
154
<span class="py-src-variable">registerAdapter</span>(<span class="py-src-variable">Counter</span>, <span class="py-src-variable">Session</span>, <span class="py-src-variable">ICounter</span>)
 
155
 
 
156
<span class="py-src-keyword">class</span> <span class="py-src-identifier">CounterResource</span>(<span class="py-src-parameter">Resource</span>):
 
157
    <span class="py-src-keyword">def</span> <span class="py-src-identifier">render_GET</span>(<span class="py-src-parameter">self</span>, <span class="py-src-parameter">request</span>):
 
158
        <span class="py-src-variable">session</span> = <span class="py-src-variable">request</span>.<span class="py-src-variable">getSession</span>()
 
159
        <span class="py-src-variable">counter</span> = <span class="py-src-variable">ICounter</span>(<span class="py-src-variable">session</span>)
 
160
        <span class="py-src-variable">counter</span>.<span class="py-src-variable">value</span> += <span class="py-src-number">1</span>
 
161
        <span class="py-src-keyword">return</span> <span class="py-src-string">&quot;Visit #%d for you!&quot;</span> % (<span class="py-src-variable">counter</span>.<span class="py-src-variable">value</span>,)
 
162
 
 
163
<span class="py-src-variable">resource</span> = <span class="py-src-variable">CounterResource</span>()
 
164
</pre>
 
165
 
 
166
<p>One more thing to note is the <code>cache()</code> call at the top of this
 
167
example. As with the <a href="http-auth.html" shape="rect">previous example</a> where this
 
168
came up, this rpy script is stateful. This time, it's the <code>ICounter</code>
 
169
definition and the
 
170
<code>registerAdapter</code> call that need to be executed only once. If we
 
171
didn't use <code>cache</code>, every request would define a new, different
 
172
interface named <code>ICounter</code>. Each of these would be a different key in
 
173
the session, so the counter would never get past one.</p>
 
174
 
 
175
</div>
 
176
 
 
177
    <p><a href="../index.html">Index</a></p>
 
178
    <span class="version">Version: 10.0.0</span>
 
179
  </body>
 
180
</html>
 
 
b'\\ No newline at end of file'