diff -r 5ff1fc726848 -r c6bca38c1cbf parts/django/docs/topics/http/sessions.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/parts/django/docs/topics/http/sessions.txt Sat Jan 08 11:20:57 2011 +0530 @@ -0,0 +1,529 @@ +=================== +How to use sessions +=================== + +.. module:: django.contrib.sessions + :synopsis: Provides session management for Django projects. + +Django provides full support for anonymous sessions. The session framework lets +you store and retrieve arbitrary data on a per-site-visitor basis. It stores +data on the server side and abstracts the sending and receiving of cookies. +Cookies contain a session ID -- not the data itself. + +Enabling sessions +================= + +Sessions are implemented via a piece of :doc:`middleware `. + +To enable session functionality, do the following: + + * Edit the ``MIDDLEWARE_CLASSES`` setting and make sure + ``MIDDLEWARE_CLASSES`` contains ``'django.contrib.sessions.middleware.SessionMiddleware'``. + The default ``settings.py`` created by ``django-admin.py startproject`` has + ``SessionMiddleware`` activated. + +If you don't want to use sessions, you might as well remove the +``SessionMiddleware`` line from ``MIDDLEWARE_CLASSES`` and ``'django.contrib.sessions'`` +from your ``INSTALLED_APPS``. It'll save you a small bit of overhead. + +Configuring the session engine +============================== + +.. versionadded:: 1.0 + +By default, Django stores sessions in your database (using the model +``django.contrib.sessions.models.Session``). Though this is convenient, in +some setups it's faster to store session data elsewhere, so Django can be +configured to store session data on your filesystem or in your cache. + +Using database-backed sessions +------------------------------ + +If you want to use a database-backed session, you need to add +``'django.contrib.sessions'`` to your ``INSTALLED_APPS`` setting. + +Once you have configured your installation, run ``manage.py syncdb`` +to install the single database table that stores session data. + +Using cached sessions +--------------------- + +For better performance, you may want to use a cache-based session backend. + +.. versionchanged:: 1.1 + Django 1.0 did not include the ``cached_db`` session backend. + +To store session data using Django's cache system, you'll first need to make +sure you've configured your cache; see the :doc:`cache documentation +` for details. + +.. warning:: + + You should only use cache-based sessions if you're using the Memcached + cache backend. The local-memory cache backend doesn't retain data long + enough to be a good choice, and it'll be faster to use file or database + sessions directly instead of sending everything through the file or + database cache backends. + +Once your cache is configured, you've got two choices for how to store data in +the cache: + + * Set :setting:`SESSION_ENGINE` to + ``"django.contrib.sessions.backends.cache"`` for a simple caching session + store. Session data will be stored directly your cache. However, session + data may not be persistent: cached data can be evicted if the cache fills + up or if the cache server is restarted. + + * For persistent, cached data, set :setting:`SESSION_ENGINE` to + ``"django.contrib.sessions.backends.cached_db"``. This uses a + write-through cache -- every write to the cache will also be written to + the database. Session reads only use the database if the data is not + already in the cache. + +Both session stores are quite fast, but the simple cache is faster because it +disregards persistence. In most cases, the ``cached_db`` backend will be fast +enough, but if you need that last bit of performance, and are willing to let +session data be expunged from time to time, the ``cache`` backend is for you. + +If you use the ``cached_db`` session backend, you also need to follow the +configuration instructions for the `using database-backed sessions`_. + +Using file-based sessions +------------------------- + +To use file-based sessions, set the ``SESSION_ENGINE`` setting to +``"django.contrib.sessions.backends.file"``. + +You might also want to set the ``SESSION_FILE_PATH`` setting (which defaults +to output from ``tempfile.gettempdir()``, most likely ``/tmp``) to control +where Django stores session files. Be sure to check that your Web server has +permissions to read and write to this location. + + +Using sessions in views +======================= + +When ``SessionMiddleware`` is activated, each ``HttpRequest`` object -- the +first argument to any Django view function -- will have a ``session`` +attribute, which is a dictionary-like object. You can read it and write to it. + +A session object has the following standard dictionary methods: + + * ``__getitem__(key)`` + + Example: ``fav_color = request.session['fav_color']`` + + * ``__setitem__(key, value)`` + + Example: ``request.session['fav_color'] = 'blue'`` + + * ``__delitem__(key)`` + + Example: ``del request.session['fav_color']``. This raises ``KeyError`` + if the given ``key`` isn't already in the session. + + * ``__contains__(key)`` + + Example: ``'fav_color' in request.session`` + + * ``get(key, default=None)`` + + Example: ``fav_color = request.session.get('fav_color', 'red')`` + + * ``keys()`` + + * ``items()`` + + * ``setdefault()`` + + * ``clear()`` + +.. versionadded:: 1.0 + ``setdefault()`` and ``clear()`` are new in this version. + +It also has these methods: + + * ``flush()`` + + .. versionadded:: 1.0 + + Delete the current session data from the session and regenerate the + session key value that is sent back to the user in the cookie. This is + used if you want to ensure that the previous session data can't be + accessed again from the user's browser (for example, the + :func:`django.contrib.auth.logout()` function calls it). + + * ``set_test_cookie()`` + + Sets a test cookie to determine whether the user's browser supports + cookies. Due to the way cookies work, you won't be able to test this + until the user's next page request. See `Setting test cookies`_ below for + more information. + + * ``test_cookie_worked()`` + + Returns either ``True`` or ``False``, depending on whether the user's + browser accepted the test cookie. Due to the way cookies work, you'll + have to call ``set_test_cookie()`` on a previous, separate page request. + See `Setting test cookies`_ below for more information. + + * ``delete_test_cookie()`` + + Deletes the test cookie. Use this to clean up after yourself. + + * ``set_expiry(value)`` + + .. versionadded:: 1.0 + + Sets the expiration time for the session. You can pass a number of + different values: + + * If ``value`` is an integer, the session will expire after that + many seconds of inactivity. For example, calling + ``request.session.set_expiry(300)`` would make the session expire + in 5 minutes. + + * If ``value`` is a ``datetime`` or ``timedelta`` object, the + session will expire at that specific date/time. + + * If ``value`` is ``0``, the user's session cookie will expire + when the user's Web browser is closed. + + * If ``value`` is ``None``, the session reverts to using the global + session expiry policy. + + Reading a session is not considered activity for expiration + purposes. Session expiration is computed from the last time the + session was *modified*. + + * ``get_expiry_age()`` + + .. versionadded:: 1.0 + + Returns the number of seconds until this session expires. For sessions + with no custom expiration (or those set to expire at browser close), this + will equal ``settings.SESSION_COOKIE_AGE``. + + * ``get_expiry_date()`` + + .. versionadded:: 1.0 + + Returns the date this session will expire. For sessions with no custom + expiration (or those set to expire at browser close), this will equal the + date ``settings.SESSION_COOKIE_AGE`` seconds from now. + + * ``get_expire_at_browser_close()`` + + .. versionadded:: 1.0 + + Returns either ``True`` or ``False``, depending on whether the user's + session cookie will expire when the user's Web browser is closed. + +You can edit ``request.session`` at any point in your view. You can edit it +multiple times. + +Session object guidelines +------------------------- + + * Use normal Python strings as dictionary keys on ``request.session``. This + is more of a convention than a hard-and-fast rule. + + * Session dictionary keys that begin with an underscore are reserved for + internal use by Django. + + * Don't override ``request.session`` with a new object, and don't access or + set its attributes. Use it like a Python dictionary. + +Examples +-------- + +This simplistic view sets a ``has_commented`` variable to ``True`` after a user +posts a comment. It doesn't let a user post a comment more than once:: + + def post_comment(request, new_comment): + if request.session.get('has_commented', False): + return HttpResponse("You've already commented.") + c = comments.Comment(comment=new_comment) + c.save() + request.session['has_commented'] = True + return HttpResponse('Thanks for your comment!') + +This simplistic view logs in a "member" of the site:: + + def login(request): + m = Member.objects.get(username=request.POST['username']) + if m.password == request.POST['password']: + request.session['member_id'] = m.id + return HttpResponse("You're logged in.") + else: + return HttpResponse("Your username and password didn't match.") + +...And this one logs a member out, according to ``login()`` above:: + + def logout(request): + try: + del request.session['member_id'] + except KeyError: + pass + return HttpResponse("You're logged out.") + +The standard ``django.contrib.auth.logout()`` function actually does a bit +more than this to prevent inadvertent data leakage. It calls +``request.session.flush()``. We are using this example as a demonstration of +how to work with session objects, not as a full ``logout()`` implementation. + +Setting test cookies +==================== + +As a convenience, Django provides an easy way to test whether the user's +browser accepts cookies. Just call ``request.session.set_test_cookie()`` in a +view, and call ``request.session.test_cookie_worked()`` in a subsequent view -- +not in the same view call. + +This awkward split between ``set_test_cookie()`` and ``test_cookie_worked()`` +is necessary due to the way cookies work. When you set a cookie, you can't +actually tell whether a browser accepted it until the browser's next request. + +It's good practice to use ``delete_test_cookie()`` to clean up after yourself. +Do this after you've verified that the test cookie worked. + +Here's a typical usage example:: + + def login(request): + if request.method == 'POST': + if request.session.test_cookie_worked(): + request.session.delete_test_cookie() + return HttpResponse("You're logged in.") + else: + return HttpResponse("Please enable cookies and try again.") + request.session.set_test_cookie() + return render_to_response('foo/login_form.html') + +Using sessions out of views +=========================== + +.. versionadded:: 1.0 + +An API is available to manipulate session data outside of a view:: + + >>> from django.contrib.sessions.backends.db import SessionStore + >>> s = SessionStore(session_key='2b1189a188b44ad18c35e113ac6ceead') + >>> s['last_login'] = datetime.datetime(2005, 8, 20, 13, 35, 10) + >>> s['last_login'] + datetime.datetime(2005, 8, 20, 13, 35, 0) + >>> s.save() + +If you're using the ``django.contrib.sessions.backends.db`` backend, each +session is just a normal Django model. The ``Session`` model is defined in +``django/contrib/sessions/models.py``. Because it's a normal model, you can +access sessions using the normal Django database API:: + + >>> from django.contrib.sessions.models import Session + >>> s = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead') + >>> s.expire_date + datetime.datetime(2005, 8, 20, 13, 35, 12) + +Note that you'll need to call ``get_decoded()`` to get the session dictionary. +This is necessary because the dictionary is stored in an encoded format:: + + >>> s.session_data + 'KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj...' + >>> s.get_decoded() + {'user_id': 42} + +When sessions are saved +======================= + +By default, Django only saves to the session database when the session has been +modified -- that is if any of its dictionary values have been assigned or +deleted:: + + # Session is modified. + request.session['foo'] = 'bar' + + # Session is modified. + del request.session['foo'] + + # Session is modified. + request.session['foo'] = {} + + # Gotcha: Session is NOT modified, because this alters + # request.session['foo'] instead of request.session. + request.session['foo']['bar'] = 'baz' + +In the last case of the above example, we can tell the session object +explicitly that it has been modified by setting the ``modified`` attribute on +the session object:: + + request.session.modified = True + +To change this default behavior, set the ``SESSION_SAVE_EVERY_REQUEST`` setting +to ``True``. If ``SESSION_SAVE_EVERY_REQUEST`` is ``True``, Django will save +the session to the database on every single request. + +Note that the session cookie is only sent when a session has been created or +modified. If ``SESSION_SAVE_EVERY_REQUEST`` is ``True``, the session cookie +will be sent on every request. + +Similarly, the ``expires`` part of a session cookie is updated each time the +session cookie is sent. + +Browser-length sessions vs. persistent sessions +=============================================== + +You can control whether the session framework uses browser-length sessions vs. +persistent sessions with the ``SESSION_EXPIRE_AT_BROWSER_CLOSE`` setting. + +By default, ``SESSION_EXPIRE_AT_BROWSER_CLOSE`` is set to ``False``, which +means session cookies will be stored in users' browsers for as long as +``SESSION_COOKIE_AGE``. Use this if you don't want people to have to log in +every time they open a browser. + +If ``SESSION_EXPIRE_AT_BROWSER_CLOSE`` is set to ``True``, Django will use +browser-length cookies -- cookies that expire as soon as the user closes his or +her browser. Use this if you want people to have to log in every time they open +a browser. + +.. versionadded:: 1.0 + +This setting is a global default and can be overwritten at a per-session level +by explicitly calling ``request.session.set_expiry()`` as described above in +`using sessions in views`_. + +Clearing the session table +========================== + +If you're using the database backend, note that session data can accumulate in +the ``django_session`` database table and Django does *not* provide automatic +purging. Therefore, it's your job to purge expired sessions on a regular basis. + +To understand this problem, consider what happens when a user uses a session. +When a user logs in, Django adds a row to the ``django_session`` database +table. Django updates this row each time the session data changes. If the user +logs out manually, Django deletes the row. But if the user does *not* log out, +the row never gets deleted. + +Django provides a sample clean-up script: ``django-admin.py cleanup``. +That script deletes any session in the session table whose ``expire_date`` is +in the past -- but your application may have different requirements. + +Settings +======== + +A few :doc:`Django settings ` give you control over session behavior: + +SESSION_ENGINE +-------------- + +.. versionadded:: 1.0 + +.. versionchanged:: 1.1 + The ``cached_db`` backend was added + +Default: ``django.contrib.sessions.backends.db`` + +Controls where Django stores session data. Valid values are: + + * ``'django.contrib.sessions.backends.db'`` + * ``'django.contrib.sessions.backends.file'`` + * ``'django.contrib.sessions.backends.cache'`` + * ``'django.contrib.sessions.backends.cached_db'`` + +See `configuring the session engine`_ for more details. + +SESSION_FILE_PATH +----------------- + +.. versionadded:: 1.0 + +Default: ``/tmp/`` + +If you're using file-based session storage, this sets the directory in +which Django will store session data. + +SESSION_COOKIE_AGE +------------------ + +Default: ``1209600`` (2 weeks, in seconds) + +The age of session cookies, in seconds. + +SESSION_COOKIE_DOMAIN +--------------------- + +Default: ``None`` + +The domain to use for session cookies. Set this to a string such as +``".lawrence.com"`` (note the leading dot!) for cross-domain cookies, or use +``None`` for a standard domain cookie. + +SESSION_COOKIE_NAME +------------------- + +Default: ``'sessionid'`` + +The name of the cookie to use for sessions. This can be whatever you want. + +SESSION_COOKIE_PATH +------------------- + +.. versionadded:: 1.0 + +Default: ``'/'`` + +The path set on the session cookie. This should either match the URL path of +your Django installation or be parent of that path. + +This is useful if you have multiple Django instances running under the same +hostname. They can use different cookie paths, and each instance will only see +its own session cookie. + +SESSION_COOKIE_SECURE +--------------------- + +Default: ``False`` + +Whether to use a secure cookie for the session cookie. If this is set to +``True``, the cookie will be marked as "secure," which means browsers may +ensure that the cookie is only sent under an HTTPS connection. + +SESSION_EXPIRE_AT_BROWSER_CLOSE +------------------------------- + +Default: ``False`` + +Whether to expire the session when the user closes his or her browser. See +"Browser-length sessions vs. persistent sessions" above. + +SESSION_SAVE_EVERY_REQUEST +-------------------------- + +Default: ``False`` + +Whether to save the session data on every request. If this is ``False`` +(default), then the session data will only be saved if it has been modified -- +that is, if any of its dictionary values have been assigned or deleted. + +.. _Django settings: ../settings/ + +Technical details +================= + + * The session dictionary should accept any pickleable Python object. See + `the pickle module`_ for more information. + + * Session data is stored in a database table named ``django_session`` . + + * Django only sends a cookie if it needs to. If you don't set any session + data, it won't send a session cookie. + +.. _`the pickle module`: http://docs.python.org/library/pickle.html + +Session IDs in URLs +=================== + +The Django sessions framework is entirely, and solely, cookie-based. It does +not fall back to putting session IDs in URLs as a last resort, as PHP does. +This is an intentional design decision. Not only does that behavior make URLs +ugly, it makes your site vulnerable to session-ID theft via the "Referer" +header.