db.py 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. import logging
  2. from django.contrib.sessions.backends.base import SessionBase, CreateError
  3. from django.core.exceptions import SuspiciousOperation
  4. from django.db import IntegrityError, transaction, router
  5. from django.utils import timezone
  6. from django.utils.encoding import force_text
  7. class SessionStore(SessionBase):
  8. """
  9. Implements database session store.
  10. """
  11. def __init__(self, session_key=None):
  12. super(SessionStore, self).__init__(session_key)
  13. def load(self):
  14. try:
  15. s = Session.objects.get(
  16. session_key=self.session_key,
  17. expire_date__gt=timezone.now()
  18. )
  19. return self.decode(s.session_data)
  20. except (Session.DoesNotExist, SuspiciousOperation) as e:
  21. if isinstance(e, SuspiciousOperation):
  22. logger = logging.getLogger('django.security.%s' %
  23. e.__class__.__name__)
  24. logger.warning(force_text(e))
  25. self.create()
  26. return {}
  27. def exists(self, session_key):
  28. return Session.objects.filter(session_key=session_key).exists()
  29. def create(self):
  30. while True:
  31. self._session_key = self._get_new_session_key()
  32. try:
  33. # Save immediately to ensure we have a unique entry in the
  34. # database.
  35. self.save(must_create=True)
  36. except CreateError:
  37. # Key wasn't unique. Try again.
  38. continue
  39. self.modified = True
  40. self._session_cache = {}
  41. return
  42. def save(self, must_create=False):
  43. """
  44. Saves the current session data to the database. If 'must_create' is
  45. True, a database error will be raised if the saving operation doesn't
  46. create a *new* entry (as opposed to possibly updating an existing
  47. entry).
  48. """
  49. obj = Session(
  50. session_key=self._get_or_create_session_key(),
  51. session_data=self.encode(self._get_session(no_load=must_create)),
  52. expire_date=self.get_expiry_date()
  53. )
  54. using = router.db_for_write(Session, instance=obj)
  55. try:
  56. with transaction.atomic(using=using):
  57. obj.save(force_insert=must_create, using=using)
  58. except IntegrityError:
  59. if must_create:
  60. raise CreateError
  61. raise
  62. def delete(self, session_key=None):
  63. if session_key is None:
  64. if self.session_key is None:
  65. return
  66. session_key = self.session_key
  67. try:
  68. Session.objects.get(session_key=session_key).delete()
  69. except Session.DoesNotExist:
  70. pass
  71. @classmethod
  72. def clear_expired(cls):
  73. Session.objects.filter(expire_date__lt=timezone.now()).delete()
  74. # At bottom to avoid circular import
  75. from django.contrib.sessions.models import Session