summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/releases/1.9.txt5
-rw-r--r--docs/topics/http/sessions.txt177
2 files changed, 179 insertions, 3 deletions
diff --git a/docs/releases/1.9.txt b/docs/releases/1.9.txt
index 1a5c488d0f..35b45ead43 100644
--- a/docs/releases/1.9.txt
+++ b/docs/releases/1.9.txt
@@ -254,7 +254,10 @@ Minor features
:mod:`django.contrib.sessions`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-* ...
+* The session model and ``SessionStore`` classes for the ``db`` and
+ ``cached_db`` backends are refactored to allow a custom database session
+ backend to build upon them. See
+ :ref:`extending-database-backed-session-engines` for more details.
:mod:`django.contrib.sitemaps`
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/docs/topics/http/sessions.txt b/docs/topics/http/sessions.txt
index 3a825f28cb..da9e5ef567 100644
--- a/docs/topics/http/sessions.txt
+++ b/docs/topics/http/sessions.txt
@@ -514,8 +514,10 @@ access sessions using the normal Django database API::
>>> 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::
+Note that you'll need to call
+:meth:`~base_session.AbstractBaseSession.get_decoded()` to get the session
+dictionary. This is necessary because the dictionary is stored in an encoded
+format::
>>> s.session_data
'KGRwMQpTJ19hdXRoX3VzZXJfaWQnCnAyCkkxCnMuMTExY2ZjODI2Yj...'
@@ -670,6 +672,177 @@ Technical details
* 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 ``SessionStore`` object
+---------------------------
+
+When working with sessions internally, Django uses a session store object from
+the corresponding session engine. By convention, the session store object class
+is named ``SessionStore`` and is located in the module designated by
+:setting:`SESSION_ENGINE`.
+
+All ``SessionStore`` classes available in Django inherit from
+:class:`~backends.base.SessionBase` and implement data manipulation methods,
+namely:
+
+* ``exists()``
+* ``create()``
+* ``save()``
+* ``delete()``
+* ``load()``
+* :meth:`~backends.base.SessionBase.clear_expired`
+
+In order to build a custom session engine or to customize an existing one, you
+may create a new class inheriting from :class:`~backends.base.SessionBase` or
+any other existing ``SessionStore`` class.
+
+Extending most of the session engines is quite straightforward, but doing so
+with database-backed session engines generally requires some extra effort (see
+the next section for details).
+
+.. _extending-database-backed-session-engines:
+
+Extending database-backed session engines
+=========================================
+
+.. versionadded:: 1.9
+
+Creating a custom database-backed session engine built upon those included in
+Django (namely ``db`` and ``cached_db``) may be done by inheriting
+:class:`~base_session.AbstractBaseSession` and either ``SessionStore`` class.
+
+``AbstractBaseSession`` and ``BaseSessionManager`` are importable from
+``django.contrib.sessions.base_session`` so that they can be imported without
+including ``django.contrib.sessions`` in :setting:`INSTALLED_APPS`.
+
+.. class:: base_session.AbstractBaseSession
+
+ .. versionadded:: 1.9
+
+ The abstract base session model.
+
+ .. attribute:: session_key
+
+ Primary key. The field itself may contain up to 40 characters. The
+ current implementation generates a 32-character string (a random
+ sequence of digits and lowercase ASCII letters).
+
+ .. attribute:: session_data
+
+ A string containing an encoded and serialized session dictionary.
+
+ .. attribute:: expire_date
+
+ A datetime designating when the session expires.
+
+ Expired sessions are not available to a user, however, they may still
+ be stored in the database until the :djadmin:`clearsessions` management
+ command is run.
+
+ .. classmethod:: get_session_store_class()
+
+ Returns a session store class to be used with this session model.
+
+ .. method:: get_decoded()
+
+ Returns decoded session data.
+
+ Decoding is performed by the session store class.
+
+You can also customize the model manager by subclassing
+:class:`~django.contrib.sessions.base_session.BaseSessionManager`:
+
+.. class:: base_session.BaseSessionManager
+
+ .. versionadded:: 1.9
+
+ .. method:: encode(session_dict)
+
+ Returns the given session dictionary serialized and encoded as a string.
+
+ Encoding is performed by the session store class tied to a model class.
+
+ .. method:: save(session_key, session_dict, expire_date)
+
+ Saves session data for a provided session key, or deletes the session
+ in case the data is empty.
+
+Customization of ``SessionStore`` classes is achieved by overriding methods
+and properties described below:
+
+.. class:: backends.db.SessionStore
+
+ Implements database-backed session store.
+
+ .. classmethod:: get_model_class()
+
+ .. versionadded:: 1.9
+
+ Override this method to return a custom session model if you need one.
+
+ .. method:: create_model_instance(data)
+
+ .. versionadded:: 1.9
+
+ Returns a new instance of the session model object, which represents
+ the current session state.
+
+ Overriding this method provides the ability to modify session model
+ data before it's saved to database.
+
+.. class:: backends.cached_db.SessionStore
+
+ Implements cached database-backed session store.
+
+ .. attribute:: cache_key_prefix
+
+ .. versionadded:: 1.9
+
+ A prefix added to a session key to build a cache key string.
+
+Example
+-------
+
+The example below shows a custom database-backed session engine that includes
+an additional database column to store an account ID (thus providing an option
+to query the database for all active sessions for an account)::
+
+ from django.contrib.sessions.backends.db import SessionStore as DBStore
+ from django.contrib.sessions.base_session import AbstractBaseSession
+ from django.db import models
+
+ class CustomSession(AbstractBaseSession):
+ account_id = models.IntegerField(null=True, db_index=True)
+
+ class Meta:
+ app_label = 'mysessions'
+
+ @classmethod
+ def get_session_store_class(cls):
+ return SessionStore
+
+ class SessionStore(DBStore):
+ @classmethod
+ def get_model_class(cls):
+ return CustomSession
+
+ def create_model_instance(self, data):
+ obj = super(SessionStore, self).create_model_instance(data)
+ try:
+ account_id = int(data.get('_auth_user_id'))
+ except (ValueError, TypeError):
+ account_id = None
+ obj.account_id = account_id
+ return obj
+
+If you are migrating from the Django's built-in ``cached_db`` session store to
+a custom one based on ``cached_db``, you should override the cache key prefix
+in order to prevent a namespace clash::
+
+ class SessionStore(CachedDBStore):
+ cache_key_prefix = 'mysessions.custom_cached_db_backend'
+
+ # ...
+
Session IDs in URLs
===================