Fixed #2066: session data can now be stored in the cache or on the filesystem. This should be fully backwards-compatible (the database cache store is still the default). A big thanks to John D'Agostino for the bulk of this code.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@6333 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Jacob Kaplan-Moss 2007-09-15 21:29:14 +00:00
parent e6460e4134
commit bcf7e9a9fe
13 changed files with 469 additions and 122 deletions

View File

@ -87,6 +87,7 @@ answer newbie questions, and generally made Django that much better:
Matt Croydon <http://www.postneo.com/> Matt Croydon <http://www.postneo.com/>
flavio.curella@gmail.com flavio.curella@gmail.com
Jure Cuhalev <gandalf@owca.info> Jure Cuhalev <gandalf@owca.info>
John D'Agostino <john.dagostino@gmail.com>
dackze+django@gmail.com dackze+django@gmail.com
David Danier <goliath.mailinglist@gmx.de> David Danier <goliath.mailinglist@gmx.de>
Dirk Datzert <dummy@habmalnefrage.de> Dirk Datzert <dummy@habmalnefrage.de>

View File

@ -271,12 +271,14 @@ MIDDLEWARE_CLASSES = (
# SESSIONS # # SESSIONS #
############ ############
SESSION_COOKIE_NAME = 'sessionid' # Cookie name. This can be whatever you want. 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_AGE = 60 * 60 * 24 * 7 * 2 # Age of cookie, in seconds (default: 2 weeks).
SESSION_COOKIE_DOMAIN = None # A string like ".lawrence.com", or None for standard domain cookie. SESSION_COOKIE_DOMAIN = None # A string like ".lawrence.com", or None for standard domain cookie.
SESSION_COOKIE_SECURE = False # Whether the session cookie should be secure (https:// only). SESSION_COOKIE_SECURE = False # Whether the session cookie should be secure (https:// only).
SESSION_SAVE_EVERY_REQUEST = False # Whether to save the session data on every request. SESSION_SAVE_EVERY_REQUEST = False # Whether to save the session data on every request.
SESSION_EXPIRE_AT_BROWSER_CLOSE = False # Whether sessions expire when a user closes his browser. SESSION_EXPIRE_AT_BROWSER_CLOSE = False # Whether sessions expire when a user closes his browser.
SESSION_ENGINE = 'django.contrib.sessions.backends.db' # The module to store session data
SESSION_FILE_PATH = '/tmp/' # Directory to store session files if using the file session module
######### #########
# CACHE # # CACHE #

View File

@ -0,0 +1,143 @@
import base64
import md5
import os
import random
import sys
import time
from django.conf import settings
from django.core.exceptions import SuspiciousOperation
try:
import cPickle as pickle
except ImportError:
import pickle
class SessionBase(object):
"""
Base class for all Session classes.
"""
TEST_COOKIE_NAME = 'testcookie'
TEST_COOKIE_VALUE = 'worked'
def __init__(self, session_key=None):
self._session_key = session_key
self.accessed = False
self.modified = False
def __contains__(self, key):
return key in self._session
def __getitem__(self, key):
return self._session[key]
def __setitem__(self, key, value):
self._session[key] = value
self.modified = True
def __delitem__(self, key):
del self._session[key]
self.modified = True
def keys(self):
return self._session.keys()
def items(self):
return self._session.items()
def get(self, key, default=None):
return self._session.get(key, default)
def pop(self, key, *args):
return self._session.pop(key, *args)
def set_test_cookie(self):
self[self.TEST_COOKIE_NAME] = self.TEST_COOKIE_VALUE
def test_cookie_worked(self):
return self.get(self.TEST_COOKIE_NAME) == self.TEST_COOKIE_VALUE
def delete_test_cookie(self):
del self[self.TEST_COOKIE_NAME]
def encode(self, session_dict):
"Returns the given session dictionary pickled and encoded as a string."
pickled = pickle.dumps(session_dict, pickle.HIGHEST_PROTOCOL)
pickled_md5 = md5.new(pickled + settings.SECRET_KEY).hexdigest()
return base64.encodestring(pickled + pickled_md5)
def decode(self, session_data):
encoded_data = base64.decodestring(session_data)
pickled, tamper_check = encoded_data[:-32], encoded_data[-32:]
if md5.new(pickled + settings.SECRET_KEY).hexdigest() != tamper_check:
raise SuspiciousOperation("User tampered with session cookie.")
try:
return pickle.loads(pickled)
# Unpickling can cause a variety of exceptions. If something happens,
# just return an empty dictionary (an empty session).
except:
return {}
def _get_new_session_key(self):
"Returns session key that isn't being used."
# The random module is seeded when this Apache child is created.
# Use settings.SECRET_KEY as added salt.
while 1:
session_key = md5.new("%s%s%s%s" % (random.randint(0, sys.maxint - 1),
os.getpid(), time.time(), settings.SECRET_KEY)).hexdigest()
if not self.exists(session_key):
break
return session_key
def _get_session_key(self):
if self._session_key:
return self._session_key
else:
self._session_key = self._get_new_session_key()
return self._session_key
def _set_session_key(self, session_key):
self._session_key = session_key
session_key = property(_get_session_key, _set_session_key)
def _get_session(self):
# Lazily loads session from storage.
self.accessed = True
try:
return self._session_cache
except AttributeError:
if self.session_key is None:
self._session_cache = {}
else:
self._session_cache = self.load()
return self._session_cache
_session = property(_get_session)
# Methods that child classes must implement.
def exists(self, session_key):
"""
Returns True if the given session_key already exists.
"""
raise NotImplementedError
def save(self):
"""
Saves the session data.
"""
raise NotImplementedError
def delete(self, session_key):
"""
Clears out the session data under this key.
"""
raise NotImplementedError
def load(self):
"""
Loads the session data and returns a dictionary.
"""
raise NotImplementedError

View File

@ -0,0 +1,26 @@
from django.conf import settings
from django.contrib.sessions.backends.base import SessionBase
from django.core.cache import cache
class SessionStore(SessionBase):
"""
A cache-based session store.
"""
def __init__(self, session_key=None):
self._cache = cache
super(SessionStore, self).__init__(session_key)
def load(self):
session_data = self._cache.get(self.session_key)
return session_data or {}
def save(self):
self._cache.set(self.session_key, self._session, settings.SESSION_COOKIE_AGE)
def exists(self, session_key):
if self._cache.get(session_key):
return True
return False
def delete(self, session_key):
self._cache.delete(session_key)

View File

@ -0,0 +1,49 @@
from django.conf import settings
from django.contrib.sessions.models import Session
from django.contrib.sessions.backends.base import SessionBase
from django.core.exceptions import SuspiciousOperation
import datetime
class SessionStore(SessionBase):
"""
Implements database session store
"""
def __init__(self, session_key=None):
super(SessionStore, self).__init__(session_key)
def load(self):
try:
s = Session.objects.get(
session_key = self.session_key,
expire_date__gt=datetime.datetime.now()
)
return self.decode(s.session_data)
except (Session.DoesNotExist, SuspiciousOperation):
# Create a new session_key for extra security.
self.session_key = self._get_new_session_key()
self._session_cache = {}
# Save immediately to minimize collision
self.save()
return {}
def exists(self, session_key):
try:
Session.objects.get(session_key=session_key)
except Session.DoesNotExist:
return False
return True
def save(self):
Session.objects.create(
session_key = self.session_key,
session_data = self.encode(self._session),
expire_date = datetime.datetime.now() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE)
)
def delete(self, session_key):
try:
Session.objects.get(session_key=session_key).delete()
except Session.DoesNotExist:
pass

View File

@ -0,0 +1,67 @@
import os
from django.conf import settings
from django.contrib.sessions.backends.base import SessionBase
from django.core.exceptions import SuspiciousOperation
class SessionStore(SessionBase):
"""
Implements a file based session store.
"""
def __init__(self, session_key=None):
self.storage_path = settings.SESSION_FILE_PATH
self.file_prefix = settings.SESSION_COOKIE_NAME
super(SessionStore, self).__init__(session_key)
def _key_to_file(self, session_key=None):
"""
Get the file associated with this session key.
"""
if session_key is None:
session_key = self.session_key
# Make sure we're not vulnerable to directory traversal. Session keys
# should always be md5s, so they should never contain directory components.
if os.path.sep in session_key:
raise SuspiciousOperation("Invalid characters (directory components) in session key")
return os.path.join(self.storage_path, self.file_prefix + session_key)
def load(self):
session_data = {}
try:
session_file = open(self._key_to_file(), "rb")
try:
session_data = self.decode(session_file.read())
except(EOFError, SuspiciousOperation):
self._session_key = self._get_new_session_key()
self._session_cache = {}
self.save()
finally:
session_file.close()
except(IOError):
pass
return session_data
def save(self):
try:
f = open(self._key_to_file(self.session_key), "wb")
try:
f.write(self.encode(self._session))
finally:
f.close()
except(IOError, EOFError):
pass
def exists(self, session_key):
if os.path.exists(self._key_to_file(session_key)):
return True
return False
def delete(self, session_key):
try:
os.unlink(self._key_to_file(session_key))
except OSError:
pass
def clean(self):
pass

View File

@ -1,6 +1,4 @@
from django.conf import settings from django.conf import settings
from django.contrib.sessions.models import Session
from django.core.exceptions import SuspiciousOperation
from django.utils.cache import patch_vary_headers from django.utils.cache import patch_vary_headers
from email.Utils import formatdate from email.Utils import formatdate
import datetime import datetime
@ -9,73 +7,11 @@ import time
TEST_COOKIE_NAME = 'testcookie' TEST_COOKIE_NAME = 'testcookie'
TEST_COOKIE_VALUE = 'worked' TEST_COOKIE_VALUE = 'worked'
class SessionWrapper(object):
def __init__(self, session_key):
self.session_key = session_key
self.accessed = False
self.modified = False
def __contains__(self, key):
return key in self._session
def __getitem__(self, key):
return self._session[key]
def __setitem__(self, key, value):
self._session[key] = value
self.modified = True
def __delitem__(self, key):
del self._session[key]
self.modified = True
def keys(self):
return self._session.keys()
def items(self):
return self._session.items()
def get(self, key, default=None):
return self._session.get(key, default)
def pop(self, key, *args):
self.modified = self.modified or key in self._session
return self._session.pop(key, *args)
def set_test_cookie(self):
self[TEST_COOKIE_NAME] = TEST_COOKIE_VALUE
def test_cookie_worked(self):
return self.get(TEST_COOKIE_NAME) == TEST_COOKIE_VALUE
def delete_test_cookie(self):
del self[TEST_COOKIE_NAME]
def _get_session(self):
# Lazily loads session from storage.
self.accessed = True
try:
return self._session_cache
except AttributeError:
if self.session_key is None:
self._session_cache = {}
else:
try:
s = Session.objects.get(session_key=self.session_key,
expire_date__gt=datetime.datetime.now())
self._session_cache = s.get_decoded()
except (Session.DoesNotExist, SuspiciousOperation):
self._session_cache = {}
# Set the session_key to None to force creation of a new
# key, for extra security.
self.session_key = None
return self._session_cache
_session = property(_get_session)
class SessionMiddleware(object): class SessionMiddleware(object):
def process_request(self, request): def process_request(self, request):
request.session = SessionWrapper(request.COOKIES.get(settings.SESSION_COOKIE_NAME, None)) engine = __import__(settings.SESSION_ENGINE, {}, {}, [''])
request.session = engine.SessionStore(request.COOKIES.get(settings.SESSION_COOKIE_NAME, None))
def process_response(self, request, response): def process_response(self, request, response):
# If request.session was modified, or if response.session was set, save # If request.session was modified, or if response.session was set, save
@ -89,25 +25,22 @@ class SessionMiddleware(object):
if accessed: if accessed:
patch_vary_headers(response, ('Cookie',)) patch_vary_headers(response, ('Cookie',))
if modified or settings.SESSION_SAVE_EVERY_REQUEST: if modified or settings.SESSION_SAVE_EVERY_REQUEST:
if request.session.session_key:
session_key = request.session.session_key
else:
obj = Session.objects.get_new_session_object()
session_key = obj.session_key
if settings.SESSION_EXPIRE_AT_BROWSER_CLOSE: if settings.SESSION_EXPIRE_AT_BROWSER_CLOSE:
max_age = None max_age = None
expires = None expires = None
else: else:
max_age = settings.SESSION_COOKIE_AGE max_age = settings.SESSION_COOKIE_AGE
rfcdate = formatdate(time.time() + settings.SESSION_COOKIE_AGE) rfcdate = formatdate(time.time() + settings.SESSION_COOKIE_AGE)
# Fixed length date must have '-' separation in the format # Fixed length date must have '-' separation in the format
# DD-MMM-YYYY for compliance with Netscape cookie standard # DD-MMM-YYYY for compliance with Netscape cookie standard
expires = (rfcdate[:7] + "-" + rfcdate[8:11] expires = datetime.datetime.strftime(datetime.datetime.utcnow() + \
+ "-" + rfcdate[12:26] + "GMT") datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE), "%a, %d-%b-%Y %H:%M:%S GMT")
new_session = Session.objects.save(session_key, request.session._session,
datetime.datetime.now() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE)) # Save the seesion data and refresh the client cookie.
response.set_cookie(settings.SESSION_COOKIE_NAME, session_key, request.session.save()
response.set_cookie(settings.SESSION_COOKIE_NAME, request.session.session_key,
max_age=max_age, expires=expires, domain=settings.SESSION_COOKIE_DOMAIN, max_age=max_age, expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
secure=settings.SESSION_COOKIE_SECURE or None) secure=settings.SESSION_COOKIE_SECURE or None)
return response return response

View File

@ -1,4 +1,4 @@
import base64, md5, random, sys, datetime, os, time import base64, md5, random, sys, datetime
import cPickle as pickle import cPickle as pickle
from django.db import models from django.db import models
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
@ -74,6 +74,7 @@ class Session(models.Model):
session_data = models.TextField(_('session data')) session_data = models.TextField(_('session data'))
expire_date = models.DateTimeField(_('expire date')) expire_date = models.DateTimeField(_('expire date'))
objects = SessionManager() objects = SessionManager()
class Meta: class Meta:
db_table = 'django_session' db_table = 'django_session'
verbose_name = _('session') verbose_name = _('session')

View File

@ -1,35 +1,59 @@
r""" r"""
>>> s = SessionWrapper(None)
Inject data into the session cache. >>> from django.contrib.sessions.backends.db import SessionStore as DatabaseSession
>>> s._session_cache = {} >>> from django.contrib.sessions.backends.cache import SessionStore as CacheSession
>>> s._session_cache['some key'] = 'exists' >>> from django.contrib.sessions.backends.file import SessionStore as FileSession
>>> s.accessed >>> db_session = DatabaseSession()
>>> db_session.modified
False False
>>> s.modified >>> db_session['cat'] = "dog"
False >>> db_session.modified
True
>>> s.pop('non existant key', 'does not exist') >>> db_session.pop('cat')
'dog'
>>> db_session.pop('some key', 'does not exist')
'does not exist' 'does not exist'
>>> s.accessed >>> db_session.save()
>>> db_session.exists(db_session.session_key)
True True
>>> s.modified >>> db_session.delete(db_session.session_key)
>>> db_session.exists(db_session.session_key)
False False
>>> s.pop('some key') >>> file_session = FileSession()
'exists' >>> file_session.modified
>>> s.accessed False
>>> file_session['cat'] = "dog"
>>> file_session.modified
True True
>>> s.modified >>> file_session.pop('cat')
True 'dog'
>>> file_session.pop('some key', 'does not exist')
>>> s.pop('some key', 'does not exist')
'does not exist' 'does not exist'
>>> file_session.save()
>>> file_session.exists(file_session.session_key)
True
>>> file_session.delete(file_session.session_key)
>>> file_session.exists(file_session.session_key)
False
>>> cache_session = CacheSession()
>>> cache_session.modified
False
>>> cache_session['cat'] = "dog"
>>> cache_session.modified
True
>>> cache_session.pop('cat')
'dog'
>>> cache_session.pop('some key', 'does not exist')
'does not exist'
>>> cache_session.save()
>>> cache_session.delete(cache_session.session_key)
>>> cache_session.exists(cache_session.session_key)
False
""" """
from django.contrib.sessions.middleware import SessionWrapper
if __name__ == '__main__': if __name__ == '__main__':
import doctest import doctest
doctest.testmod() doctest.testmod()

View File

@ -4,8 +4,6 @@ from cStringIO import StringIO
from urlparse import urlparse from urlparse import urlparse
from django.conf import settings from django.conf import settings
from django.contrib.auth import authenticate, login from django.contrib.auth import authenticate, login
from django.contrib.sessions.models import Session
from django.contrib.sessions.middleware import SessionWrapper
from django.core.handlers.base import BaseHandler from django.core.handlers.base import BaseHandler
from django.core.handlers.wsgi import WSGIRequest from django.core.handlers.wsgi import WSGIRequest
from django.core.signals import got_request_exception from django.core.signals import got_request_exception
@ -132,9 +130,10 @@ class Client:
def _session(self): def _session(self):
"Obtain the current session variables" "Obtain the current session variables"
if 'django.contrib.sessions' in settings.INSTALLED_APPS: if 'django.contrib.sessions' in settings.INSTALLED_APPS:
engine = __import__(settings.SESSION_ENGINE, {}, {}, [''])
cookie = self.cookies.get(settings.SESSION_COOKIE_NAME, None) cookie = self.cookies.get(settings.SESSION_COOKIE_NAME, None)
if cookie: if cookie:
return SessionWrapper(cookie.value) return engine.SessionClass(cookie.value)
return {} return {}
session = property(_session) session = property(_session)
@ -247,24 +246,23 @@ class Client:
""" """
user = authenticate(**credentials) user = authenticate(**credentials)
if user and user.is_active and 'django.contrib.sessions' in settings.INSTALLED_APPS: if user and user.is_active and 'django.contrib.sessions' in settings.INSTALLED_APPS:
obj = Session.objects.get_new_session_object() engine = __import__(settings.SESSION_ENGINE, {}, {}, [''])
# Create a fake request to store login details # Create a fake request to store login details
request = HttpRequest() request = HttpRequest()
request.session = SessionWrapper(obj.session_key) request.session = engine.SessionClass()
login(request, user) login(request, user)
# Set the cookie to represent the session # Set the cookie to represent the session
self.cookies[settings.SESSION_COOKIE_NAME] = obj.session_key self.cookies[settings.SESSION_COOKIE_NAME] = request.session.session_key
self.cookies[settings.SESSION_COOKIE_NAME]['max-age'] = None self.cookies[settings.SESSION_COOKIE_NAME]['max-age'] = None
self.cookies[settings.SESSION_COOKIE_NAME]['path'] = '/' self.cookies[settings.SESSION_COOKIE_NAME]['path'] = '/'
self.cookies[settings.SESSION_COOKIE_NAME]['domain'] = settings.SESSION_COOKIE_DOMAIN self.cookies[settings.SESSION_COOKIE_NAME]['domain'] = settings.SESSION_COOKIE_DOMAIN
self.cookies[settings.SESSION_COOKIE_NAME]['secure'] = settings.SESSION_COOKIE_SECURE or None self.cookies[settings.SESSION_COOKIE_NAME]['secure'] = settings.SESSION_COOKIE_SECURE or None
self.cookies[settings.SESSION_COOKIE_NAME]['expires'] = None self.cookies[settings.SESSION_COOKIE_NAME]['expires'] = None
# Set the session values # Save the session values
Session.objects.save(obj.session_key, request.session._session, request.session.save()
datetime.datetime.now() + datetime.timedelta(seconds=settings.SESSION_COOKIE_AGE))
return True return True
else: else:

View File

@ -10,18 +10,21 @@ Cookies contain a session ID -- not the data itself.
Enabling sessions Enabling sessions
================= =================
Sessions are implemented via a piece of middleware_ and a Django model. Sessions are implemented via a piece of middleware_.
To enable session functionality, do these two things: To enable session functionality, do the following:
* Edit the ``MIDDLEWARE_CLASSES`` setting and make sure * Edit the ``MIDDLEWARE_CLASSES`` setting and make sure
``MIDDLEWARE_CLASSES`` contains ``'django.contrib.sessions.middleware.SessionMiddleware'``. ``MIDDLEWARE_CLASSES`` contains ``'django.contrib.sessions.middleware.SessionMiddleware'``.
The default ``settings.py`` created by ``django-admin.py startproject`` has The default ``settings.py`` created by ``django-admin.py startproject`` has
``SessionMiddleware`` activated. ``SessionMiddleware`` activated.
* Add ``'django.contrib.sessions'`` to your ``INSTALLED_APPS`` setting, and * Add ``'django.contrib.sessions'`` to your ``INSTALLED_APPS`` setting,
run ``manage.py syncdb`` to install the single database table that stores and run ``manage.py syncdb`` to install the single database table
session data. that stores session data.
**New in development version**: this step is optional if you're not using
the database session backend; see `configuring the session engine`_.
If you don't want to use sessions, you might as well remove the If you don't want to use sessions, you might as well remove the
``SessionMiddleware`` line from ``MIDDLEWARE_CLASSES`` and ``'django.contrib.sessions'`` ``SessionMiddleware`` line from ``MIDDLEWARE_CLASSES`` and ``'django.contrib.sessions'``
@ -29,6 +32,44 @@ from your ``INSTALLED_APPS``. It'll save you a small bit of overhead.
.. _middleware: ../middleware/ .. _middleware: ../middleware/
Configuring the session engine
==============================
**New in development version**.
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 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 ``/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 `cache documentation`_ for details.
.. _cache documentation: ../cache/
.. note::
You probably don't want to use cache-based sessions if you're not using
the memcached cache backend. The local memory and simple cache backends
don't retain data long enough to be good choices, 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 Using sessions in views
======================= =======================
@ -153,14 +194,25 @@ Here's a typical usage example::
Using sessions out of views Using sessions out of views
=========================== ===========================
Internally, each session is just a normal Django model. The ``Session`` model The ``SessionStore`` which implements the session storage method can be imported
and a API is available to manipulate the session data outside of a view::
>>> from django.contrib.sessions.engines.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()
Or if you are using the ``django.contrib.sessions.engine.db`` each
session is just a normal Django model. The ``Session`` model
is defined in ``django/contrib/sessions/models.py``. Because it's a normal is defined in ``django/contrib/sessions/models.py``. Because it's a normal
model, you can access sessions using the normal Django database API:: model, you can access sessions using the normal Django database API::
>>> from django.contrib.sessions.models import Session >>> from django.contrib.sessions.models import Session
>>> s = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead') >>> s = Session.objects.get(pk='2b1189a188b44ad18c35e113ac6ceead')
>>> s.expire_date >>> s.expire_date
datetime.datetime(2005, 8, 20, 13, 35, 12) datetime.datetime(2005, 8, 20, 13, 35, 12)
Note that you'll need to call ``get_decoded()`` to get the session dictionary. 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:: This is necessary because the dictionary is stored in an encoded format::
@ -245,6 +297,31 @@ Settings
A few `Django settings`_ give you control over session behavior: A few `Django settings`_ give you control over session behavior:
SESSION_ENGINE
--------------
**New in Django development version**
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'``
See `configuring the session engine`_ for more details.
SESSION_FILE_PATH
-----------------
**New in Django development version**
Default: ``/tmp/``
If you're using file-based session storage, this sets the directory in
which Django will store session data.
SESSION_COOKIE_AGE SESSION_COOKIE_AGE
------------------ ------------------

View File

@ -733,6 +733,21 @@ Default: ``'root@localhost'``
The e-mail address that error messages come from, such as those sent to The e-mail address that error messages come from, such as those sent to
``ADMINS`` and ``MANAGERS``. ``ADMINS`` and ``MANAGERS``.
SESSION_ENGINE
--------------
**New in Django development version**
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'``
See the `session docs`_ for more details.
SESSION_COOKIE_AGE SESSION_COOKIE_AGE
------------------ ------------------
@ -775,6 +790,17 @@ Default: ``False``
Whether to expire the session when the user closes his or her browser. Whether to expire the session when the user closes his or her browser.
See the `session docs`_. See the `session docs`_.
SESSION_FILE_PATH
-----------------
**New in Django development version**
Default: ``/tmp/``
If you're using file-based session storage, this sets the directory in
which Django will store session data. See the `session docs`_ for
more details.
SESSION_SAVE_EVERY_REQUEST SESSION_SAVE_EVERY_REQUEST
-------------------------- --------------------------