18

From django's documentation, I became under the impression that calling:

request.session.set_expiry(300)

from one view would cause the session to expire after five minutes inactivity; however, this is not the behavior that I'm experiencing in django trunk. If I call this method from one view, and browse around to other views that don't call the method, the session expires in five minutes. The behavior that I was expecting was an expiry only after five minutes of inactivity and not simply failing to call set_expiry again before the expiry.

My question then is do I really need to call set_expiry in every view? If so, does there exist some decorator that may be of assistance? I can't imagine this isn't part of contrib.

Thanks, Pete

slypete
  • 5,538
  • 11
  • 47
  • 64

3 Answers3

33

As the author of those methods, I can see that the documentation isn't very clear regarding this. Your observations are correct: only requests which cause the session to be altered is considered "activity".

You can use the SESSION_SAVE_EVERY_REQUEST setting to get the behavior you're after (at the obvious cost of the session having to being saved every request).

Note : It will update the existing session record with latest expiry date.

brainLoop
  • 3,810
  • 2
  • 10
  • 13
SmileyChris
  • 10,578
  • 4
  • 40
  • 33
4

A simple middleware would probably do better than setting this up in every view. This is what I used.

class SessionExpiry(object):
    """ Set the session expiry according to settings """
    def process_request(self, request):
        if getattr(settings, 'SESSION_EXPIRY', None):
            request.session.set_expiry(settings.SESSION_EXPIRY)
        return None

This depends on SESSION_EXPIRY being set in your config. It's format is the same as request.session.set_expiry.

MIDDLEWARE_CLASSES should be defined with this order in mind:

MIDDLEWARE_CLASSES = (
    ...
    'django.contrib.sessions.middleware.SessionMiddleware',
    '<yourproject>.<yourapp>.middleware.SessionExpiry',
    ...
}

It'd be nice if django.contrib.sessions took this setting into account by default.

Mike Shultz
  • 1,368
  • 1
  • 15
  • 32
  • Did you miss SmileyChris' answer? `SESSION_SAVE_EVERY_REQUEST` does exactly this without any custom middleware. – slypete Oct 28 '12 at 03:53
  • 2
    Yes, but only having set_expiry called in one view requires all your users to hit that specific view(s) that sets the expiry. It's unlikely your users will funnel through a this specific view. With the middleware you can abstract this expiration set outside of a view. If his answer works for you, cool. I just thought this might be a cleaner way of doing it and it's the way I chose to go about it. – Mike Shultz Oct 28 '12 at 16:47
  • I think you misunderstood the answer. `SESSION_SAVE_EVERY_REQUEST` does exactly what you're doing without any view specific code. I'm just pointing out that you reinvented the wheel. – slypete Oct 28 '12 at 20:36
  • 2
    That setting forces expiry to be updated, yes, but it doesn't set the expiry. So no, it doesn't do exactly the same thing. My middleware allows you to set the expiry to an arbitrary value. – Mike Shultz Oct 29 '12 at 18:35
  • 3
    While `SESSION_SAVE_EVERY_REQUEST` is useful if you want a global expire policy, defining a custom middleware allows you to customize it more. For instance, if the request is coming from an IP the user marked as "trusted", it can set it to never expire (or to a very long value, updated at every request). Otherwise, it can set it to a short value. Etc. So it's not exactly "reinventing the wheel", but an alternative method that can be useful in some circumstances. – mgibsonbr Feb 17 '13 at 00:21
  • I agree with @Mike, global settings are a better fit for middleware than for a login specific view. A login specific view won't handle the admin logins either. – freb Apr 06 '15 at 22:45
  • I consider a middleware solution too. setting SESSION_SAVE_EVERY_REQUEST, will have a performance hit of writing to the session table on every request. I think of a different policy to extend session expiry: `if session_expiry - now < TIME_DELTA` , only then extend the session. – user3599803 Jul 13 '16 at 21:02
0

If you set "True" to SESSION_SAVE_EVERY_REQUEST on "settings.py" as shown below, automatically, session is updated every time the current page is reopened or other page is opened in Django Website.

SESSION_SAVE_EVERY_REQUEST = True # False by default

For example, session expires in 15 minutes. Then, from 3:00 pm, a session starts by logging in the page in Django Website so the session expires at 3:15 pm. Then, at 3:10 pm, the current page is reopened or other page is opened in Django Website so the session is updated so the new session expires at 3:25 pm which means you are logged in until 3:25 pm, so in other words, if the current page is not reopened or other page is not opened in Django Website then the new session expires at 3:25 pm which means you are logged out at 3:25 pm so you need to log in again to the page in Django Website to start a new session.

Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129