From 146ed13a111c97c1c04902a6c0eda1e4ee6e604c Mon Sep 17 00:00:00 2001 From: Aymeric Augustin Date: Tue, 30 Oct 2012 21:59:23 +0100 Subject: [PATCH] Fixed #17083 -- Allowed sessions to use non-default cache. --- django/conf/global_settings.py | 1 + django/contrib/sessions/backends/cache.py | 5 +++-- django/contrib/sessions/tests.py | 26 +++++++++++++++++++---- docs/ref/settings.txt | 10 +++++++++ docs/releases/1.5.txt | 3 +++ docs/topics/http/sessions.txt | 9 ++++++++ 6 files changed, 48 insertions(+), 6 deletions(-) diff --git a/django/conf/global_settings.py b/django/conf/global_settings.py index 84296c7493..c533efc41c 100644 --- a/django/conf/global_settings.py +++ b/django/conf/global_settings.py @@ -445,6 +445,7 @@ MIDDLEWARE_CLASSES = ( # SESSIONS # ############ +SESSION_CACHE_ALIAS = 'default' # Cache to store session data if using the cache session backend. SESSION_COOKIE_NAME = 'sessionid' # Cookie name. This can be whatever you want. SESSION_COOKIE_AGE = 60 * 60 * 24 * 7 * 2 # Age of cookie, in seconds (default: 2 weeks). SESSION_COOKIE_DOMAIN = None # A string like ".example.com", or None for standard domain cookie. diff --git a/django/contrib/sessions/backends/cache.py b/django/contrib/sessions/backends/cache.py index 1b4906f923..596042fcb3 100644 --- a/django/contrib/sessions/backends/cache.py +++ b/django/contrib/sessions/backends/cache.py @@ -1,5 +1,6 @@ +from django.conf import settings from django.contrib.sessions.backends.base import SessionBase, CreateError -from django.core.cache import cache +from django.core.cache import get_cache from django.utils.six.moves import xrange KEY_PREFIX = "django.contrib.sessions.cache" @@ -10,7 +11,7 @@ class SessionStore(SessionBase): A cache-based session store. """ def __init__(self, session_key=None): - self._cache = cache + self._cache = get_cache(settings.SESSION_CACHE_ALIAS) super(SessionStore, self).__init__(session_key) @property diff --git a/django/contrib/sessions/tests.py b/django/contrib/sessions/tests.py index 718967791d..da79ac9de6 100644 --- a/django/contrib/sessions/tests.py +++ b/django/contrib/sessions/tests.py @@ -13,8 +13,8 @@ from django.contrib.sessions.backends.file import SessionStore as FileSession from django.contrib.sessions.backends.signed_cookies import SessionStore as CookieSession from django.contrib.sessions.models import Session from django.contrib.sessions.middleware import SessionMiddleware +from django.core.cache import get_cache from django.core import management -from django.core.cache import DEFAULT_CACHE_ALIAS from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation from django.http import HttpResponse from django.test import TestCase, RequestFactory @@ -136,8 +136,8 @@ class SessionTestsMixin(object): self.assertTrue(self.session.modified) def test_save(self): - if (hasattr(self.session, '_cache') and - 'DummyCache' in settings.CACHES[DEFAULT_CACHE_ALIAS]['BACKEND']): + if (hasattr(self.session, '_cache') and'DummyCache' in + settings.CACHES[settings.SESSION_CACHE_ALIAS]['BACKEND']): raise unittest.SkipTest("Session saving tests require a real cache backend") self.session.save() self.assertTrue(self.session.exists(self.session.session_key)) @@ -355,7 +355,8 @@ class CacheDBSessionTests(SessionTestsMixin, TestCase): backend = CacheDBSession - @unittest.skipIf('DummyCache' in settings.CACHES[DEFAULT_CACHE_ALIAS]['BACKEND'], + @unittest.skipIf('DummyCache' in + settings.CACHES[settings.SESSION_CACHE_ALIAS]['BACKEND'], "Session saving tests require a real cache backend") def test_exists_searches_cache_first(self): self.session.save() @@ -454,6 +455,23 @@ class CacheSessionTests(SessionTestsMixin, unittest.TestCase): self.session._session_key = (string.ascii_letters + string.digits) * 20 self.assertEqual(self.session.load(), {}) + def test_default_cache(self): + self.session.save() + self.assertNotEqual(get_cache('default').get(self.session.cache_key), None) + + @override_settings(CACHES={ + 'default': { + 'BACKEND': 'django.core.cache.backends.dummy.DummyCache', + }, + 'sessions': { + 'BACKEND': 'django.core.cache.backends.locmem.LocMemCache', + }, + }, SESSION_CACHE_ALIAS='sessions') + def test_non_default_cache(self): + self.session.save() + self.assertEqual(get_cache('default').get(self.session.cache_key), None) + self.assertNotEqual(get_cache('sessions').get(self.session.cache_key), None) + class SessionMiddlewareTests(unittest.TestCase): diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt index a909c12665..e8b41afb39 100644 --- a/docs/ref/settings.txt +++ b/docs/ref/settings.txt @@ -1693,6 +1693,16 @@ 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. +.. setting:: SESSION_CACHE_ALIAS + +SESSION_CACHE_ALIAS +------------------- + +Default: ``default`` + +If you're using :ref:`cache-based session storage `, +this selects the cache to use. + .. setting:: SESSION_COOKIE_SECURE SESSION_COOKIE_SECURE diff --git a/docs/releases/1.5.txt b/docs/releases/1.5.txt index 3ee1b2d21f..e18a78afc8 100644 --- a/docs/releases/1.5.txt +++ b/docs/releases/1.5.txt @@ -299,6 +299,9 @@ Django 1.5 also includes several smaller improvements worth noting: * RemoteUserMiddleware now forces logout when the REMOTE_USER header disappears during the same browser session. +* The :ref:`cache-based session backend ` can store + session data in a non-default cache. + Backwards incompatible changes in 1.5 ===================================== diff --git a/docs/topics/http/sessions.txt b/docs/topics/http/sessions.txt index d9c472d092..baf8aa5cb5 100644 --- a/docs/topics/http/sessions.txt +++ b/docs/topics/http/sessions.txt @@ -45,6 +45,8 @@ If you want to use a database-backed session, you need to add Once you have configured your installation, run ``manage.py syncdb`` to install the single database table that stores session data. +.. _cached-sessions-backend: + Using cached sessions --------------------- @@ -62,6 +64,13 @@ sure you've configured your cache; see the :doc:`cache documentation sessions directly instead of sending everything through the file or database cache backends. +If you have multiple caches defined in :setting:`CACHES`, Django will use the +default cache. To use another cache, set :setting:`SESSION_CACHE_ALIAS` to the +name of that cache. + +.. versionchanged:: 1.5 + The :setting:`SESSION_CACHE_ALIAS` setting was added. + Once your cache is configured, you've got two choices for how to store data in the cache: