|
1 from django.contrib.sessions.backends.base import SessionBase, CreateError |
|
2 from django.core.cache import cache |
|
3 |
|
4 class SessionStore(SessionBase): |
|
5 """ |
|
6 A cache-based session store. |
|
7 """ |
|
8 def __init__(self, session_key=None): |
|
9 self._cache = cache |
|
10 super(SessionStore, self).__init__(session_key) |
|
11 |
|
12 def load(self): |
|
13 session_data = self._cache.get(self.session_key) |
|
14 if session_data is not None: |
|
15 return session_data |
|
16 self.create() |
|
17 return {} |
|
18 |
|
19 def create(self): |
|
20 # Because a cache can fail silently (e.g. memcache), we don't know if |
|
21 # we are failing to create a new session because of a key collision or |
|
22 # because the cache is missing. So we try for a (large) number of times |
|
23 # and then raise an exception. That's the risk you shoulder if using |
|
24 # cache backing. |
|
25 for i in xrange(10000): |
|
26 self.session_key = self._get_new_session_key() |
|
27 try: |
|
28 self.save(must_create=True) |
|
29 except CreateError: |
|
30 continue |
|
31 self.modified = True |
|
32 return |
|
33 raise RuntimeError("Unable to create a new session key.") |
|
34 |
|
35 def save(self, must_create=False): |
|
36 if must_create: |
|
37 func = self._cache.add |
|
38 else: |
|
39 func = self._cache.set |
|
40 result = func(self.session_key, self._get_session(no_load=must_create), |
|
41 self.get_expiry_age()) |
|
42 if must_create and not result: |
|
43 raise CreateError |
|
44 |
|
45 def exists(self, session_key): |
|
46 if self._cache.has_key(session_key): |
|
47 return True |
|
48 return False |
|
49 |
|
50 def delete(self, session_key=None): |
|
51 if session_key is None: |
|
52 if self._session_key is None: |
|
53 return |
|
54 session_key = self._session_key |
|
55 self._cache.delete(session_key) |
|
56 |