Search code examples
djangosessionsession-cookiesdjango-sessions

django save data to session without increasing its expiry


Basically I want to do something like:

request.session['last_date'] = datetime.datetime.now()

without django modify (increase) session expire_date (i.e, it should stay as it is)

I have SESSION_SAVE_EVERY_REQUEST = True

The session expiry should remain unchanged when last_date is modified as above. However for all other changes expiry should change. I do not want to set it as a global policy for the session.


Solution

  • When you want to change the default behavior of the session engine, the usual practice is to write a custom session backend. Fortunately, it isn't very difficult. We will make ours by subclassing django.contrib.session.backends.db.SessionStore

    from django.contrib.session.backends.db import SessionStore as DbStore

    class SessionStore(DbStore):
    
        def load(self):
            try:
                self.current_session = self.model.objects.get(
                    session_key=self.session_key,
                    expire_date__gt=timezone.now()
                )
                return self.decode(s.session_data)
            except (self.model.DoesNotExist, SuspiciousOperation) as e:
                if isinstance(e, SuspiciousOperation):
                    logger = logging.getLogger('django.security.%s' % e.__class__.__name__)
                    logger.warning(force_text(e))
                self._session_key = None
                return {}
    
        def create_model_instance(self, data):
            """
            Return a new instance of the session model object, which represents the
            current session state. Intended to be used for saving the session data
            to the database.
            """
            try:
                expiry = self.current_session.expire_date
            except AttributeError:
                expiry = None
    
            return self.model(
                session_key=self._get_or_create_session_key(),
                session_data=self.encode(data),
                expire_date=self.get_expiry_date(expiry=expiry),
            )
    

    Most of the code is from django.contrib with few slight modificiations. Now all you have to do is to tell django to use our new session store by modifying the settings.py

    SESSION_ENGINE = 'myapp.session'
    

    Assuming that you put the above code in a file named session.py

    Response to edit in question:

    This code shows how to modify the session with out changing it's expiry time. Now you mention you want this behavour only if the last_date item is changed, make a modification as follows;

            expiry = None
    
            try:
                if current_session.get('last_date') != date.get('last_date') :    
                    expiry = self.current_session.expire_date
            except AttributeError:
                pass