summaryrefslogtreecommitdiff
path: root/docs/tutorials/zodbsessions/index.rst
blob: 9582e5de43c89f418f11157a63cf9b30eac2e4e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
.. _zodb_sessions:

Using ZODB-Based Sessions
=========================

Sessions are server-side namespaces which are associated with a site
user that expire automatically after some period of disuse.

If your application is ZODB-based (e.g. you've created an application
from the ``bfg_zodb`` paster template, or you've followed the
instructions in :ref:`zodb_with_zeo`), you can make use of the
``repoze.session`` and ``repoze.browserid`` packages to add
sessioning to your application.

.. note:: You can use the ``repoze.session`` package even if your
   application is not ZODB-based, but its backing store requires ZODB,
   so it makes the most sense to use this package if your application
   already uses ZODB.  This tutorial does not cover usage of
   ``repoze.session``-based sessions in applications that don't
   already use ZODB.  For this, see `the standalone repoze.session
   usage documentation <http://docs.repoze.org/session/usage.html>`_.
   If you don't want to use ZODB to do sessioning, you might choose to
   use a relational/filestorage sessioning system such as `Beaker
   <http://pypi.python.org/pypi/Beaker>`_.  :app:`Pyramid` is fully
   compatible with this system too.

Installing Dependencies
-----------------------

#. Edit your :app:`Pyramid` application's ``setup.py`` file, adding
   the following packages to the ``install_requires`` of the
   application:

   - ``repoze.session``

   - ``repoze.browserid``

   For example, the relevant portion of your application's
   ``setup.py`` file might look like so when you're finished adding
   the dependencies.

   .. code-block:: python
      :linenos:

      setup(
          # ... other elements left out for brevity
          install_requires=[
                'pyramid',
                'repoze.folder',
                'repoze.retry',
                'repoze.tm2',
                'repoze.zodbconn',
                'repoze.session'
                'repoze.browserid',
                ],
          # ... other elements left out for brevity
           )

#. Rerun your application's ``setup.py`` file (e.g. using ``python
   setup.py develop``) to get these packages installed.

Configuration
-------------

#. Edit your application's Paste ``.ini`` file.

   If you already have an ``app`` section in the ``.ini`` file named
   ``main``, rename this section to ``myapp`` (e.g. ``app:main`` ->
   ``app:myapp``).  Add a key to it named ``zodb_uri``, e.g.

   .. code-block:: python
      :linenos:

      [app:myapp]
      use = egg:myapp#app
      zodb_uri = zeo://%(here)s/zeo.sock
      reload_templates = true
      debug_authorization = false
      debug_notfound = false

   Add a ``filter`` section to the ``.ini`` file named "browserid":

   .. code-block:: python
      :linenos:

      [filter:browserid]
      use = egg:repoze.browserid#browserid
      secret_key = my-secret-key

   Replace ``my-secret-key`` with any random string.  This string
   represents the value which the client-side "browser id" cookie is
   encrypted with, to prevent tampering.

   If a ``pipeline`` named ``main`` does not already exist in the
   paste ``.ini`` file , add a ``pipeline`` section named ``main``.
   Put the names ``connector``, ``egg:repoze.retry#retry``, and
   ``egg:repoze.tm2#tm`` to the top of the pipeline.

   .. code-block:: python
      :linenos:

      [pipeline:main]
      pipeline = 
             browserid
             egg:repoze.retry#retry
             egg:repoze.tm2#tm
             myapp

   When you're finished, your ``.ini`` file might look like so:

   .. code-block:: ini
      :linenos:

      [DEFAULT]
      debug = true

      [app:myapp]
      use = egg:myapp#app
      zodb_uri = zeo://%(here)s/zeo.sock
      reload_templates = true
      debug_authorization = false
      debug_notfound = false

      [filter:browserid]
      use = egg:repoze.browserid#browserid
      secret_key = my-secret-key

      [pipeline:main]
      pipeline = 
             browserid
             egg:repoze.retry#retry
             egg:repoze.tm2#tm
             myapp

      [server:main]
      use = egg:Paste#http
      host = 0.0.0.0
      port = 6543

   See :ref:`MyProject_ini` for more information about project Paste
   ``.ini`` files.

#.  Add a ``get_session`` API to your application.  I've chosen to add
    it directly to my ``views.py`` file, although it can live anywhere.

    .. code-block:: python
       :linenos:

       from repoze.session.manager import SessionDataManager
       from pyramid.traversal import find_root

       def get_session(context, request):
           root = find_root(context)
           if not hasattr(root, '_sessions'):
               root._sessions = SessionDataManager(3600, 5)
           session = root._sessions.get(request.environ['repoze.browserid'])
           return session

    Note in the call to ``SessionDataManager`` that '3600' represents
    the disuse timeout (60 minutes == 3600 seconds), and '5' represents
    a write granularity time (the session will be marked as active at
    most every five seconds).  Vary these values as necessary.

#.  Whenever you want to use a session in your application, call this API:

    .. code-block:: python
       :linenos:

       from repoze.session.manager import SessionDataManager
       from pyramid.traversal import find_root
       from pyramid.chameleon_zpt import render_template_to_response

       def my_view(context, request):
           session = get_session(context, request)
           session['abc'] = '123'
           return render_template_to_response('templates/mytemplate.pt',
                                              request = request,
                                              project = 'sess')

       def get_session(context, request):
           root = find_root(context)
           if not hasattr(root, '_sessions'):
               root._sessions = SessionDataManager(3600, 5)
           session = root._sessions.get(request.environ['repoze.browserid'])
           return session

For more information, see the `repoze.session documentation
<http://docs.repoze.org/session/>`_ and the `repoze.browserid
documentation <http://pypi.python.org/pypi/repoze.browserid>`_.