Django 会话过期?
根据Django的文档,我原本以为调用:
request.session.set_expiry(300)
从一个视图中会导致会话在五分钟内没有活动后过期;然而,我在Django的最新版本中并没有遇到这样的情况。如果我在一个视图中调用这个方法,然后再去浏览其他不调用这个方法的视图,会话还是在五分钟后过期。我原本期待的行为是,只有在五分钟内没有任何活动后才过期,而不是因为没有在过期前再次调用set_expiry。
所以我的问题是,我真的需要在每个视图中都调用set_expiry吗?如果是这样的话,有没有什么装饰器可以帮忙?我无法想象这不是Django的一个组成部分。
谢谢,
皮特
3 个回答
如果你在settings.py文件中把"SESSION_SAVE_EVERY_REQUEST"设置为"True",就会发生一个有趣的事情:每次你在Django网站上重新打开当前页面或者打开其他页面时,session(会话)都会自动更新。
SESSION_SAVE_EVERY_REQUEST = True # False by default
举个例子,假设session的有效时间是15分钟。那么从下午3:00开始,你在Django网站上登录,这时session会在下午3:15过期。接着,如果在下午3:10时,你重新打开当前页面或者打开其他页面,session就会被更新,这样新的session会在下午3:25过期。这就意味着你可以一直保持登录状态,直到下午3:25。换句话说,如果你没有重新打开页面或者没有打开其他页面,那么新的session会在下午3:25过期,这样你就会被登出,之后需要再次登录Django网站才能开始一个新的session。
一个简单的中间件可能比在每个视图中单独设置要好。这是我使用的方式。
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
这取决于你的配置中是否设置了 SESSION_EXPIRY
。它的格式和 request.session.set_expiry
是一样的。
MIDDLEWARE_CLASSES
的定义顺序要考虑到这一点:
MIDDLEWARE_CLASSES = (
...
'django.contrib.sessions.middleware.SessionMiddleware',
'<yourproject>.<yourapp>.middleware.SessionExpiry',
...
}
如果 django.contrib.sessions
默认能考虑到这个设置就好了。
作为这些方法的作者,我发现文档在这方面并不是很清楚。你的观察是对的:只有那些会改变会话的请求才算是“活动”。
你可以使用 SESSION_SAVE_EVERY_REQUEST
这个设置来实现你想要的效果(当然,这样每次请求都会保存会话,开销会比较大)。
注意:这样会更新现有的会话记录,并且会把过期时间更新为最新的。