PageRenderTime 61ms CodeModel.GetById 51ms app.highlight 4ms RepoModel.GetById 1ms app.codeStats 0ms

/docs/topics/http/sessions.txt

https://code.google.com/p/mango-py/
Plain Text | 538 lines | 377 code | 161 blank | 0 comment | 0 complexity | 1f41101cfcdbab49bb0df490bd1a576a MD5 | raw file
  1===================
  2How to use sessions
  3===================
  4
  5.. module:: django.contrib.sessions
  6   :synopsis: Provides session management for Django projects.
  7
  8Django provides full support for anonymous sessions. The session framework lets
  9you store and retrieve arbitrary data on a per-site-visitor basis. It stores
 10data on the server side and abstracts the sending and receiving of cookies.
 11Cookies contain a session ID -- not the data itself.
 12
 13Enabling sessions
 14=================
 15
 16Sessions are implemented via a piece of :doc:`middleware </ref/middleware>`.
 17
 18To enable session functionality, do the following:
 19
 20    * Edit the :setting:`MIDDLEWARE_CLASSES` setting and make sure
 21      it contains ``'django.contrib.sessions.middleware.SessionMiddleware'``.
 22      The default ``settings.py`` created by ``django-admin.py startproject``
 23      has ``SessionMiddleware`` activated.
 24
 25If you don't want to use sessions, you might as well remove the
 26``SessionMiddleware`` line from :setting:`MIDDLEWARE_CLASSES` and
 27``'django.contrib.sessions'`` from your :setting:`INSTALLED_APPS`.
 28It'll save you a small bit of overhead.
 29
 30Configuring the session engine
 31==============================
 32
 33By default, Django stores sessions in your database (using the model
 34``django.contrib.sessions.models.Session``). Though this is convenient, in
 35some setups it's faster to store session data elsewhere, so Django can be
 36configured to store session data on your filesystem or in your cache.
 37
 38Using database-backed sessions
 39------------------------------
 40
 41If you want to use a database-backed session, you need to add
 42``'django.contrib.sessions'`` to your :setting:`INSTALLED_APPS` setting.
 43
 44Once you have configured your installation, run ``manage.py syncdb``
 45to install the single database table that stores session data.
 46
 47Using cached sessions
 48---------------------
 49
 50For better performance, you may want to use a cache-based session backend.
 51
 52To store session data using Django's cache system, you'll first need to make
 53sure you've configured your cache; see the :doc:`cache documentation
 54</topics/cache>` for details.
 55
 56.. warning::
 57
 58    You should only use cache-based sessions if you're using the Memcached
 59    cache backend. The local-memory cache backend doesn't retain data long
 60    enough to be a good choice, and it'll be faster to use file or database
 61    sessions directly instead of sending everything through the file or
 62    database cache backends.
 63
 64Once your cache is configured, you've got two choices for how to store data in
 65the cache:
 66
 67    * Set :setting:`SESSION_ENGINE` to
 68      ``"django.contrib.sessions.backends.cache"`` for a simple caching session
 69      store. Session data will be stored directly your cache. However, session
 70      data may not be persistent: cached data can be evicted if the cache fills
 71      up or if the cache server is restarted.
 72
 73    * For persistent, cached data, set :setting:`SESSION_ENGINE` to
 74      ``"django.contrib.sessions.backends.cached_db"``. This uses a
 75      write-through cache -- every write to the cache will also be written to
 76      the database. Session reads only use the database if the data is not
 77      already in the cache.
 78
 79Both session stores are quite fast, but the simple cache is faster because it
 80disregards persistence. In most cases, the ``cached_db`` backend will be fast
 81enough, but if you need that last bit of performance, and are willing to let
 82session data be expunged from time to time, the ``cache`` backend is for you.
 83
 84If you use the ``cached_db`` session backend, you also need to follow the
 85configuration instructions for the `using database-backed sessions`_.
 86
 87Using file-based sessions
 88-------------------------
 89
 90To use file-based sessions, set the :setting:`SESSION_ENGINE` setting to
 91``"django.contrib.sessions.backends.file"``.
 92
 93You might also want to set the :setting:`SESSION_FILE_PATH` setting (which
 94defaults to output from ``tempfile.gettempdir()``, most likely ``/tmp``) to
 95control where Django stores session files. Be sure to check that your Web
 96server has permissions to read and write to this location.
 97
 98
 99Using sessions in views
100=======================
101
102When ``SessionMiddleware`` is activated, each :class:`~django.http.HttpRequest`
103object -- the first argument to any Django view function -- will have a
104``session`` attribute, which is a dictionary-like object.
105
106You can read it and write to ``request.session`` at any point in your view.
107You can edit it multiple times.
108
109.. class:: backends.base.SessionBase
110
111    This is the base class for all session objects. It has the following
112    standard dictionary methods:
113
114    .. method:: __getitem__(key)
115
116      Example: ``fav_color = request.session['fav_color']``
117
118    .. method:: __setitem__(key, value)
119
120      Example: ``request.session['fav_color'] = 'blue'``
121
122    .. method:: __delitem__(key)
123
124      Example: ``del request.session['fav_color']``. This raises ``KeyError``
125      if the given ``key`` isn't already in the session.
126
127    .. method:: __contains__(key)
128
129      Example: ``'fav_color' in request.session``
130
131    .. method:: get(key, default=None)
132
133      Example: ``fav_color = request.session.get('fav_color', 'red')``
134
135    .. method:: pop(key)
136
137      Example: ``fav_color = request.session.pop('fav_color')``
138
139    .. method:: keys
140
141    .. method:: items
142
143    .. method:: setdefault
144
145    .. method:: clear
146
147    It also has these methods:
148
149    .. method:: flush
150
151      Delete the current session data from the session and regenerate the
152      session key value that is sent back to the user in the cookie. This is
153      used if you want to ensure that the previous session data can't be
154      accessed again from the user's browser (for example, the
155      :func:`django.contrib.auth.logout()` function calls it).
156
157    .. method:: set_test_cookie
158
159      Sets a test cookie to determine whether the user's browser supports
160      cookies. Due to the way cookies work, you won't be able to test this
161      until the user's next page request. See `Setting test cookies`_ below for
162      more information.
163
164    .. method:: test_cookie_worked
165
166      Returns either ``True`` or ``False``, depending on whether the user's
167      browser accepted the test cookie. Due to the way cookies work, you'll
168      have to call ``set_test_cookie()`` on a previous, separate page request.
169      See `Setting test cookies`_ below for more information.
170
171    .. method:: delete_test_cookie
172
173      Deletes the test cookie. Use this to clean up after yourself.
174
175    .. method:: set_expiry(value)
176
177      Sets the expiration time for the session. You can pass a number of
178      different values:
179
180            * If ``value`` is an integer, the session will expire after that
181              many seconds of inactivity. For example, calling
182              ``request.session.set_expiry(300)`` would make the session expire
183              in 5 minutes.
184
185            * If ``value`` is a ``datetime`` or ``timedelta`` object, the
186              session will expire at that specific date/time.
187
188            * If ``value`` is ``0``, the user's session cookie will expire
189              when the user's Web browser is closed.
190
191            * If ``value`` is ``None``, the session reverts to using the global
192              session expiry policy.
193
194      Reading a session is not considered activity for expiration
195      purposes. Session expiration is computed from the last time the
196      session was *modified*.
197
198    .. method:: get_expiry_age
199
200      Returns the number of seconds until this session expires. For sessions
201      with no custom expiration (or those set to expire at browser close), this
202      will equal :setting:`SESSION_COOKIE_AGE`.
203
204    .. method:: get_expiry_date
205
206      Returns the date this session will expire. For sessions with no custom
207      expiration (or those set to expire at browser close), this will equal the
208      date :setting:`SESSION_COOKIE_AGE` seconds from now.
209
210    .. method:: get_expire_at_browser_close
211
212      Returns either ``True`` or ``False``, depending on whether the user's
213      session cookie will expire when the user's Web browser is closed.
214
215Session object guidelines
216-------------------------
217
218    * Use normal Python strings as dictionary keys on ``request.session``. This
219      is more of a convention than a hard-and-fast rule.
220
221    * Session dictionary keys that begin with an underscore are reserved for
222      internal use by Django.
223
224    * Don't override ``request.session`` with a new object, and don't access or
225      set its attributes. Use it like a Python dictionary.
226
227Examples
228--------
229
230This simplistic view sets a ``has_commented`` variable to ``True`` after a user
231posts a comment. It doesn't let a user post a comment more than once::
232
233    def post_comment(request, new_comment):
234        if request.session.get('has_commented', False):
235            return HttpResponse("You've already commented.")
236        c = comments.Comment(comment=new_comment)
237        c.save()
238        request.session['has_commented'] = True
239        return HttpResponse('Thanks for your comment!')
240
241This simplistic view logs in a "member" of the site::
242
243    def login(request):
244        m = Member.objects.get(username=request.POST['username'])
245        if m.password == request.POST['password']:
246            request.session['member_id'] = m.id
247            return HttpResponse("You're logged in.")
248        else:
249            return HttpResponse("Your username and password didn't match.")
250
251...And this one logs a member out, according to ``login()`` above::
252
253    def logout(request):
254        try:
255            del request.session['member_id']
256        except KeyError:
257            pass
258        return HttpResponse("You're logged out.")
259
260The standard :meth:`django.contrib.auth.logout` function actually does a bit
261more than this to prevent inadvertent data leakage. It calls the
262:meth:`~backends.base.SessionBase.flush` method of ``request.session``.
263We are using this example as a demonstration of how to work with session
264objects, not as a full ``logout()`` implementation.
265
266Setting test cookies
267====================
268
269As a convenience, Django provides an easy way to test whether the user's
270browser accepts cookies. Just call the
271:meth:`~backends.base.SessionBase.set_test_cookie` method of
272``request.session`` in a view, and call
273:meth:`~backends.base.SessionBase.test_cookie_worked` in a subsequent view --
274not in the same view call.
275
276This awkward split between ``set_test_cookie()`` and ``test_cookie_worked()``
277is necessary due to the way cookies work. When you set a cookie, you can't
278actually tell whether a browser accepted it until the browser's next request.
279
280It's good practice to use
281:meth:`~backends.base.SessionBase.delete_test_cookie()` to clean up after
282yourself. Do this after you've verified that the test cookie worked.
283
284Here's a typical usage example::
285
286    def login(request):
287        if request.method == 'POST':
288            if request.session.test_cookie_worked():
289                request.session.delete_test_cookie()
290                return HttpResponse("You're logged in.")
291            else:
292                return HttpResponse("Please enable cookies and try again.")
293        request.session.set_test_cookie()
294        return render_to_response('foo/login_form.html')
295
296Using sessions out of views
297===========================
298
299An API is available to manipulate session data outside of a view::
300
301    >>> from django.contrib.sessions.backends.db import SessionStore
302    >>> import datetime
303    >>> s = SessionStore(session_key='2b1189a188b44ad18c35e113ac6ceead')
304    >>> s['last_login'] = datetime.datetime(2005, 8, 20, 13, 35, 10)
305    >>> s['last_login']
306    datetime.datetime(2005, 8, 20, 13, 35, 0)
307    >>> s.save()
308
309If ``session_key`` isn't provided, one will be generated automatically::
310
311    >>> from django.contrib.sessions.backends.db import SessionStore
312    >>> s = SessionStore()
313    >>> s.save()
314    >>> s.session_key
315    '2b1189a188b44ad18c35e113ac6ceead'
316
317If you're using the ``django.contrib.sessions.backends.db`` backend, each
318session is just a normal Django model. The ``Session`` model is defined in
319``django/contrib/sessions/models.py``. Because it's a normal model, you can
320access sessions using the normal Django database API::
321
322    >>> from django.contrib.sessions.models import Session
323    >>> s = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead')
324    >>> s.expire_date
325    datetime.datetime(2005, 8, 20, 13, 35, 12)
326
327Note that you'll need to call ``get_decoded()`` to get the session dictionary.
328This is necessary because the dictionary is stored in an encoded format::
329
330    >>> s.session_data
331    'KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj...'
332    >>> s.get_decoded()
333    {'user_id': 42}
334
335When sessions are saved
336=======================
337
338By default, Django only saves to the session database when the session has been
339modified -- that is if any of its dictionary values have been assigned or
340deleted::
341
342    # Session is modified.
343    request.session['foo'] = 'bar'
344
345    # Session is modified.
346    del request.session['foo']
347
348    # Session is modified.
349    request.session['foo'] = {}
350
351    # Gotcha: Session is NOT modified, because this alters
352    # request.session['foo'] instead of request.session.
353    request.session['foo']['bar'] = 'baz'
354
355In the last case of the above example, we can tell the session object
356explicitly that it has been modified by setting the ``modified`` attribute on
357the session object::
358
359    request.session.modified = True
360
361To change this default behavior, set the :setting:`SESSION_SAVE_EVERY_REQUEST`
362setting to ``True``. When set to ``True``, Django will save the session to the
363database on every single request.
364
365Note that the session cookie is only sent when a session has been created or
366modified. If :setting:`SESSION_SAVE_EVERY_REQUEST` is ``True``, the session
367cookie will be sent on every request.
368
369Similarly, the ``expires`` part of a session cookie is updated each time the
370session cookie is sent.
371
372Browser-length sessions vs. persistent sessions
373===============================================
374
375You can control whether the session framework uses browser-length sessions vs.
376persistent sessions with the :setting:`SESSION_EXPIRE_AT_BROWSER_CLOSE`
377setting.
378
379By default, :setting:`SESSION_EXPIRE_AT_BROWSER_CLOSE` is set to ``False``,
380which means session cookies will be stored in users' browsers for as long as
381:setting:`SESSION_COOKIE_AGE`. Use this if you don't want people to have to
382log in every time they open a browser.
383
384If :setting:`SESSION_EXPIRE_AT_BROWSER_CLOSE` is set to ``True``, Django will
385use browser-length cookies -- cookies that expire as soon as the user closes
386his or her browser. Use this if you want people to have to log in every time
387they open a browser.
388
389This setting is a global default and can be overwritten at a per-session level
390by explicitly calling the :meth:`~backends.base.SessionBase.set_expiry` method
391of ``request.session`` as described above in `using sessions in views`_.
392
393Clearing the session table
394==========================
395
396If you're using the database backend, note that session data can accumulate in
397the ``django_session`` database table and Django does *not* provide automatic
398purging. Therefore, it's your job to purge expired sessions on a regular basis.
399
400To understand this problem, consider what happens when a user uses a session.
401When a user logs in, Django adds a row to the ``django_session`` database
402table. Django updates this row each time the session data changes. If the user
403logs out manually, Django deletes the row. But if the user does *not* log out,
404the row never gets deleted.
405
406Django provides a sample clean-up script: ``django-admin.py cleanup``.
407That script deletes any session in the session table whose ``expire_date`` is
408in the past -- but your application may have different requirements.
409
410Settings
411========
412
413A few :doc:`Django settings </ref/settings>` give you control over session
414behavior:
415
416SESSION_ENGINE
417--------------
418
419Default: ``django.contrib.sessions.backends.db``
420
421Controls where Django stores session data. Valid values are:
422
423    * ``'django.contrib.sessions.backends.db'``
424    * ``'django.contrib.sessions.backends.file'``
425    * ``'django.contrib.sessions.backends.cache'``
426    * ``'django.contrib.sessions.backends.cached_db'``
427
428See `configuring the session engine`_ for more details.
429
430SESSION_FILE_PATH
431-----------------
432
433Default: ``/tmp/``
434
435If you're using file-based session storage, this sets the directory in
436which Django will store session data.
437
438SESSION_COOKIE_AGE
439------------------
440
441Default: ``1209600`` (2 weeks, in seconds)
442
443The age of session cookies, in seconds.
444
445SESSION_COOKIE_DOMAIN
446---------------------
447
448Default: ``None``
449
450The domain to use for session cookies. Set this to a string such as
451``".lawrence.com"`` (note the leading dot!) for cross-domain cookies, or use
452``None`` for a standard domain cookie.
453
454SESSION_COOKIE_HTTPONLY
455-----------------------
456
457Default: ``False``
458
459Whether to use HTTPOnly flag on the session cookie. If this is set to
460``True``, client-side JavaScript will not to be able to access the
461session cookie.
462
463HTTPOnly_ is a flag included in a Set-Cookie HTTP response header. It
464is not part of the RFC2109 standard for cookies, and it isn't honored
465consistently by all browsers. However, when it is honored, it can be a
466useful way to mitigate the risk of client side script accessing the
467protected cookie data.
468
469.. _HTTPOnly: http://www.owasp.org/index.php/HTTPOnly
470
471SESSION_COOKIE_NAME
472-------------------
473
474Default: ``'sessionid'``
475
476The name of the cookie to use for sessions. This can be whatever you want.
477
478SESSION_COOKIE_PATH
479-------------------
480
481Default: ``'/'``
482
483The path set on the session cookie. This should either match the URL path of
484your Django installation or be parent of that path.
485
486This is useful if you have multiple Django instances running under the same
487hostname. They can use different cookie paths, and each instance will only see
488its own session cookie.
489
490SESSION_COOKIE_SECURE
491---------------------
492
493Default: ``False``
494
495Whether to use a secure cookie for the session cookie. If this is set to
496``True``, the cookie will be marked as "secure," which means browsers may
497ensure that the cookie is only sent under an HTTPS connection.
498
499SESSION_EXPIRE_AT_BROWSER_CLOSE
500-------------------------------
501
502Default: ``False``
503
504Whether to expire the session when the user closes his or her browser. See
505"Browser-length sessions vs. persistent sessions" above.
506
507SESSION_SAVE_EVERY_REQUEST
508--------------------------
509
510Default: ``False``
511
512Whether to save the session data on every request. If this is ``False``
513(default), then the session data will only be saved if it has been modified --
514that is, if any of its dictionary values have been assigned or deleted.
515
516.. _Django settings: ../settings/
517
518Technical details
519=================
520
521    * The session dictionary should accept any pickleable Python object. See
522      `the pickle module`_ for more information.
523
524    * Session data is stored in a database table named ``django_session`` .
525
526    * Django only sends a cookie if it needs to. If you don't set any session
527      data, it won't send a session cookie.
528
529.. _`the pickle module`: http://docs.python.org/library/pickle.html
530
531Session IDs in URLs
532===================
533
534The Django sessions framework is entirely, and solely, cookie-based. It does
535not fall back to putting session IDs in URLs as a last resort, as PHP does.
536This is an intentional design decision. Not only does that behavior make URLs
537ugly, it makes your site vulnerable to session-ID theft via the "Referer"
538header.