summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdam Johnson <me@adamj.eu>2021-11-29 17:22:23 +0000
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2022-01-13 13:05:42 +0100
commit436862787cbdbd68b0ba20ed8c23b295e3679df3 (patch)
treefd23d005d065df8b80aa205852f3d651b5359fd4
parentc6cb5a0277fce1b87a4b417002289c31f0ee44bc (diff)
Refs #29708 -- Made SessionBase store expiry as string.
-rw-r--r--django/contrib/sessions/backends/base.py8
-rw-r--r--docs/topics/http/sessions.txt6
-rw-r--r--tests/sessions_tests/tests.py33
3 files changed, 23 insertions, 24 deletions
diff --git a/django/contrib/sessions/backends/base.py b/django/contrib/sessions/backends/base.py
index 62ee1f0d89..5374965da8 100644
--- a/django/contrib/sessions/backends/base.py
+++ b/django/contrib/sessions/backends/base.py
@@ -210,8 +210,10 @@ class SessionBase:
if not expiry: # Checks both None and 0 cases
return self.get_session_cookie_age()
- if not isinstance(expiry, datetime):
+ if not isinstance(expiry, (datetime, str)):
return expiry
+ if isinstance(expiry, str):
+ expiry = datetime.fromisoformat(expiry)
delta = expiry - modification
return delta.days * 86400 + delta.seconds
@@ -233,6 +235,8 @@ class SessionBase:
if isinstance(expiry, datetime):
return expiry
+ elif isinstance(expiry, str):
+ return datetime.fromisoformat(expiry)
expiry = expiry or self.get_session_cookie_age()
return modification + timedelta(seconds=expiry)
@@ -260,6 +264,8 @@ class SessionBase:
return
if isinstance(value, timedelta):
value = timezone.now() + value
+ if isinstance(value, datetime):
+ value = value.isoformat()
self['_session_expiry'] = value
def get_expire_at_browser_close(self):
diff --git a/docs/topics/http/sessions.txt b/docs/topics/http/sessions.txt
index 34dabdd536..ce92af7b71 100644
--- a/docs/topics/http/sessions.txt
+++ b/docs/topics/http/sessions.txt
@@ -258,10 +258,8 @@ You can edit it multiple times.
``request.session.set_expiry(300)`` would make the session expire
in 5 minutes.
- * If ``value`` is a ``datetime`` or ``timedelta`` object, the
- session will expire at that specific date/time. Note that ``datetime``
- and ``timedelta`` values are only serializable if you are using the
- :class:`~django.contrib.sessions.serializers.PickleSerializer`.
+ * If ``value`` is a ``datetime`` or ``timedelta`` object, the session
+ will expire at that specific date/time.
* If ``value`` is ``0``, the user's session cookie will expire
when the user's web browser is closed.
diff --git a/tests/sessions_tests/tests.py b/tests/sessions_tests/tests.py
index c2743ef48b..816777bc97 100644
--- a/tests/sessions_tests/tests.py
+++ b/tests/sessions_tests/tests.py
@@ -333,25 +333,20 @@ class SessionTestsMixin:
self.assertEqual(self.session.decode(encoded), {})
def test_actual_expiry(self):
- # this doesn't work with JSONSerializer (serializing timedelta)
- with override_settings(SESSION_SERIALIZER='django.contrib.sessions.serializers.PickleSerializer'):
- self.session = self.backend() # reinitialize after overriding settings
-
- # Regression test for #19200
- old_session_key = None
- new_session_key = None
- try:
- self.session['foo'] = 'bar'
- self.session.set_expiry(-timedelta(seconds=10))
- self.session.save()
- old_session_key = self.session.session_key
- # With an expiry date in the past, the session expires instantly.
- new_session = self.backend(self.session.session_key)
- new_session_key = new_session.session_key
- self.assertNotIn('foo', new_session)
- finally:
- self.session.delete(old_session_key)
- self.session.delete(new_session_key)
+ old_session_key = None
+ new_session_key = None
+ try:
+ self.session['foo'] = 'bar'
+ self.session.set_expiry(-timedelta(seconds=10))
+ self.session.save()
+ old_session_key = self.session.session_key
+ # With an expiry date in the past, the session expires instantly.
+ new_session = self.backend(self.session.session_key)
+ new_session_key = new_session.session_key
+ self.assertNotIn('foo', new_session)
+ finally:
+ self.session.delete(old_session_key)
+ self.session.delete(new_session_key)
def test_session_load_does_not_create_record(self):
"""