|
|
@@ -0,0 +1,69 @@ |
|
|
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): |
|
|
""" Write-through 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) |