diff --git a/AUTHORS b/AUTHORS index 365381c5b4..3b34c0b711 100644 --- a/AUTHORS +++ b/AUTHORS @@ -201,6 +201,7 @@ answer newbie questions, and generally made Django that much better: james_027@yahoo.com jcrasta@gmail.com jdetaeye + jhenry Zak Johnson Nis Jørgensen Michael Josephson diff --git a/django/contrib/sessions/backends/cached_db.py b/django/contrib/sessions/backends/cached_db.py new file mode 100644 index 0000000000..9e22c69228 --- /dev/null +++ b/django/contrib/sessions/backends/cached_db.py @@ -0,0 +1,42 @@ +""" +Cached, database-backed sessions. +""" + +from django.conf import settings +from django.contrib.sessions.backends.db import SessionStore as DBStore +from django.core.cache import cache + +class SessionStore(DBStore): + """ + Implements cached, database backed sessions. + """ + + def __init__(self, session_key=None): + super(SessionStore, self).__init__(session_key) + + def load(self): + data = cache.get(self.session_key, None) + if data is None: + data = super(SessionStore, self).load() + cache.set(self.session_key, data, settings.SESSION_COOKIE_AGE) + return data + + def exists(self, session_key): + return super(SessionStore, self).exists(session_key) + + def save(self, must_create=False): + super(SessionStore, self).save(must_create) + cache.set(self.session_key, self._session, settings.SESSION_COOKIE_AGE) + + def delete(self, session_key=None): + super(SessionStore, self).delete(session_key) + cache.delete(session_key or self.session_key) + + def flush(self): + """ + Removes the current session data from the database and regenerates the + key. + """ + self.clear() + self.delete(self.session_key) + self.create() \ No newline at end of file diff --git a/django/contrib/sessions/tests.py b/django/contrib/sessions/tests.py index cf6922449f..d0fed280b5 100644 --- a/django/contrib/sessions/tests.py +++ b/django/contrib/sessions/tests.py @@ -3,6 +3,7 @@ r""" >>> from django.conf import settings >>> from django.contrib.sessions.backends.db import SessionStore as DatabaseSession >>> from django.contrib.sessions.backends.cache import SessionStore as CacheSession +>>> from django.contrib.sessions.backends.cached_db import SessionStore as CacheDBSession >>> from django.contrib.sessions.backends.file import SessionStore as FileSession >>> from django.contrib.sessions.backends.base import SessionBase >>> from django.contrib.sessions.models import Session @@ -54,6 +55,31 @@ True >>> db_session.save() >>> DatabaseSession('1').get('cat') +# +# Cached DB session tests +# + +>>> cdb_session = CacheDBSession() +>>> cdb_session.modified +False +>>> cdb_session['cat'] = "dog" +>>> cdb_session.modified +True +>>> cdb_session.pop('cat') +'dog' +>>> cdb_session.pop('some key', 'does not exist') +'does not exist' +>>> cdb_session.save() +>>> cdb_session.exists(cdb_session.session_key) +True +>>> cdb_session.delete(cdb_session.session_key) +>>> cdb_session.exists(cdb_session.session_key) +False + +# +# File session tests. +# + # Do file session tests in an isolated directory, and kill it after we're done. >>> original_session_file_path = settings.SESSION_FILE_PATH >>> import tempfile diff --git a/docs/topics/http/sessions.txt b/docs/topics/http/sessions.txt index 7c28768e30..ca189c11fe 100644 --- a/docs/topics/http/sessions.txt +++ b/docs/topics/http/sessions.txt @@ -43,6 +43,46 @@ By default, Django stores sessions in your database (using the model 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 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 :ref:`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 in 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 persistant: cached data can be evicted if the cache fills + up or if the cache server is restarted. + + * For persistant, 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 +disreguards persistance. 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. + Using file-based sessions ------------------------- @@ -54,23 +94,6 @@ 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 cache-based sessions --------------------------- - -To store session data using Django's cache system, set ``SESSION_ENGINE`` -to ``"django.contrib.sessions.backends.cache"``. You'll want to make sure -you've configured your cache; see the :ref:`cache documentation ` for details. - -.. _cache documentation: ../cache/ - -.. note:: - - You should probably 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. - Using sessions in views =======================