Reputation: 8329
From Django's documentation for set_expiry
:
Reading a session is not considered activity for expiration purposes. Session expiration is computed from the last time the session was modified.
Django's default value for the SESSION_COOKIE_AGE
setting is 1209600
(2 weeks, in seconds). So if a session gets created on January 1st at midnight, it will be set to expire on January 15th at midnight. But if that session gets modified on, say, January 14th at midnight, it would then be set to expire on January 28th at midnight instead of the original January 15th at midnight.
I'm happy with the default lifetime of two weeks, but I want to know the most efficient way to make it so all sessions always expire in two weeks after they were created—even if they get modified. It seems like I would have to write some middleware to check the session creation time and then set the expiration to be two weeks after that, but it seems like there has to be a more efficient way than this.
Upvotes: 2
Views: 723
Reputation: 8026
You should extend the django.contrib.session.backends.db.SessionBase
class and modify the behavior, so just taking a quick look at that class you could look into the save(...)
and perhaps the get_expiry_date(...)
methods.
Here's an example of a custom session storage class that doesn't update the expiry_date of the session if a session with that key already exists
from django.contrib.sessions.backend.db import SessionStorage
class MySessionStore(SessionStore):
def save(self, must_create=False):
"""
Saves the current session data to the database. If 'must_create' is
True, a database error will be raised if the saving operation doesn't
create a *new* entry (as opposed to possibly updating an existing
entry).
"""
if self.session_key is None:
return self.create()
existing_session = Session.objects.filter(session_key=self.session_key)
expire_date = self.get_expiry_date()
if existing_session.exists():
# Here we select the original expire_date from the database
# so when the session is modified and saved, expire_date
# remains unchanged
if existing_session.first().expire_date is not None:
expire_date = existing_session.first().expire_date
obj = Session(
session_key=self._get_or_create_session_key(),
session_data=self.encode(self._get_session(no_load=must_create)),
expire_date=expire_date
)
using = router.db_for_write(Session, instance=obj)
try:
with transaction.atomic(using=using):
obj.save(force_insert=must_create, using=using)
except IntegrityError:
if must_create:
raise CreateError
raise
Now that we have a custom session class which won't update the expiry date every time a session is modified, we have to use our custom session class with the SESSION_ENGINE
setting as SESSION_ENGINE='path.to.MySessionStore'
I haven't tested this solution, I'm just taking a punt at an answer :)
Upvotes: 2