cached_db.py 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. """
  2. Cached, database-backed sessions.
  3. """
  4. import logging
  5. from django.conf import settings
  6. from django.contrib.sessions.backends.db import SessionStore as DBStore
  7. from django.core.cache import caches
  8. from django.core.exceptions import SuspiciousOperation
  9. from django.utils import timezone
  10. from django.utils.encoding import force_text
  11. KEY_PREFIX = "django.contrib.sessions.cached_db"
  12. class SessionStore(DBStore):
  13. """
  14. Implements cached, database backed sessions.
  15. """
  16. def __init__(self, session_key=None):
  17. self._cache = caches[settings.SESSION_CACHE_ALIAS]
  18. super(SessionStore, self).__init__(session_key)
  19. @property
  20. def cache_key(self):
  21. return KEY_PREFIX + self._get_or_create_session_key()
  22. def load(self):
  23. try:
  24. data = self._cache.get(self.cache_key, None)
  25. except Exception:
  26. # Some backends (e.g. memcache) raise an exception on invalid
  27. # cache keys. If this happens, reset the session. See #17810.
  28. data = None
  29. if data is None:
  30. # Duplicate DBStore.load, because we need to keep track
  31. # of the expiry date to set it properly in the cache.
  32. try:
  33. s = Session.objects.get(
  34. session_key=self.session_key,
  35. expire_date__gt=timezone.now()
  36. )
  37. data = self.decode(s.session_data)
  38. self._cache.set(self.cache_key, data,
  39. self.get_expiry_age(expiry=s.expire_date))
  40. except (Session.DoesNotExist, SuspiciousOperation) as e:
  41. if isinstance(e, SuspiciousOperation):
  42. logger = logging.getLogger('django.security.%s' %
  43. e.__class__.__name__)
  44. logger.warning(force_text(e))
  45. self.create()
  46. data = {}
  47. return data
  48. def exists(self, session_key):
  49. if (KEY_PREFIX + session_key) in self._cache:
  50. return True
  51. return super(SessionStore, self).exists(session_key)
  52. def save(self, must_create=False):
  53. super(SessionStore, self).save(must_create)
  54. self._cache.set(self.cache_key, self._session, self.get_expiry_age())
  55. def delete(self, session_key=None):
  56. super(SessionStore, self).delete(session_key)
  57. if session_key is None:
  58. if self.session_key is None:
  59. return
  60. session_key = self.session_key
  61. self._cache.delete(KEY_PREFIX + session_key)
  62. def flush(self):
  63. """
  64. Removes the current session data from the database and regenerates the
  65. key.
  66. """
  67. self.clear()
  68. self.delete(self.session_key)
  69. self.create()
  70. # At bottom to avoid circular import
  71. from django.contrib.sessions.models import Session