Skip to content

Instantly share code, notes, and snippets.

@mikeyk
Created April 8, 2011 18:01
Show Gist options
  • Save mikeyk/910392 to your computer and use it in GitHub Desktop.
Save mikeyk/910392 to your computer and use it in GitHub Desktop.
A redis backend for Django Sessions, tested on Django 1.3+
from django.contrib.sessions.backends.base import SessionBase, CreateError
from django.conf import settings
from django.utils.encoding import force_unicode
import redis
class SessionStore(SessionBase):
""" Redis store for sessions"""
def __init__(self, session_key=None):
self.redis = redis.Redis(
host = settings.SESSION_REDIS_HOST,
port = settings.SESSION_REDIS_PORT,
socket_timeout = settings.REDIS_SOCKET_TIMEOUT
)
super(SessionStore, self).__init__(session_key)
@classmethod
def _get_key_for_redis(self, session_key):
return 'sessionstore:%s' % session_key
def _redis_key(self):
return self.__class__._get_key_for_redis(self.session_key)
def load(self):
session_data = self.redis.get(self._redis_key())
if session_data is not None:
return self.decode(force_unicode(session_data))
else:
self.create()
return {}
def create(self):
max_attempts = 10
attempt = 0
while True:
self.session_key = self._get_new_session_key()
session_dict = self._get_session(no_load = True)
session_data = self.encode(session_dict)
was_created = self.redis.setnx(self._redis_key(),
session_data)
if was_created:
self.redis.expire(self._redis_key(),
settings.SESSION_COOKIE_AGE)
self.modified = True
self._session_cache = session_dict
return
else:
# extremely unlikely
if attempt == max_attempts:
raise CreateError
else:
attempt += 1
continue
def save(self, must_create=False):
if must_create:
self.create()
else:
encoded_data = self.encode(self._session)
self.redis.setex(self._redis_key(), encoded_data, settings.SESSION_COOKIE_AGE)
def exists(self, session_key):
return self.redis.exists(self.__class__._get_key_for_redis(session_key))
def delete(self, session_key=None):
to_delete = (session_key or self.session_key)
redis_key = self.__class__._get_key_for_redis(to_delete)
self.redis.delete(redis_key)
@darkness51
Copy link

Hello Mike,

I am testing your session backend but I am receiving the following error:

AttributeError at /directlogin/
can't set attribute

You have idea what can cause this?

Best Regards

@pchartrand
Copy link

We are testing your backend for session data, with the intent of using multiple redis servers in a replicated environment. Any hints would be appreciated.

@muhammadsa
Copy link

you should get the below block out from the class's init to avoid calling it every time it is instantiated...to be called only one time.

self.redis = redis.Redis(
host = settings.SESSION_REDIS_HOST,
port = settings.SESSION_REDIS_PORT,
socket_timeout = settings.REDIS_SOCKET_TIMEOUT
)

@wachpwnski
Copy link

I think he wants a socket or each instance he creates, not to share sockets between all instances. That's why it is self.redis is assigned in the init func.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment