我刚刚意识到,当我使用基于文件的会话引擎时,我的会话不会过期。查看基于文件的会话的 Django 代码,Django 不会为会话存储任何过期信息,因此除非手动删除会话文件,否则它永远不会过期。
这对我来说似乎是一个错误,因为数据库支持的会话工作正常,我相信无论后端开发人员选择什么会话,它们都应该表现得相似。
切换到数据库支持的会话对我来说不是一个选项,因为我需要将用户的会话存储在文件中。
任何人都可以发光吗?这真的是一个错误吗?如果是,你建议我如何解决它?
谢谢!
所以看起来你是对的。至少在 django 1.4 中,使用django.contrib.sessions.backends.file
完全忽略SESSION_COOKIE_AGE
. 我不确定这是否真的是一个错误,或者只是没有记录。
如果你真的需要这个功能,你可以基于 contrib 中的文件后端创建你自己的会话引擎,但是用过期功能扩展它。
打开django/contrib/sessions/backends/file.py
并添加以下导入:
import datetime
from django.utils import timezone
然后,在方法中添加两行load
,使其如下所示:
def load(self):
session_data = {}
try:
session_file = open(self._key_to_file(), "rb")
if (timezone.now() - datetime.datetime.fromtimestamp(os.path.getmtime(self._key_to_file()))).total_seconds() > settings.SESSION_COOKIE_AGE:
raise IOError
try:
file_data = session_file.read()
# Don't fail if there is no data in the session file.
....
这实际上将比较会话文件上的最后修改日期以使其过期。
将此文件保存在您的项目中的某处并将其用作您的SESSION_ENGINE
而不是'django.contrib.sessions.backends.file'
SESSION_SAVE_EVERY_REQUEST
如果您希望会话根据不活动状态超时,您还需要在设置中启用。
一个选项是tmpwatch
在存储会话的目录中使用
我遇到了类似的问题Django 3.1
。就我而言,我的程序在检查会话到期之前set_expiry(value)
使用整数参数(数据类型)调用该函数。int
根据Django 文档,参数的数据类型value
可以set_expiry()
是int
,datetime
或timedelta
. 但是,对于基于文件的会话,只有在预先将参数传递给的情况下,内部的到期检查load()
才能正常工作,并且此类问题不会发生在.int
set_expiry()
datetime
timedelta
set_expiry()
简单的解决方案(解决方法?)是避免int
参数set_expiry(value)
,您可以通过子类化django.contrib.sessions.backends.file.SessionStore
和覆盖来做到这一点set_expiry(value)
(下面的代码示例),并SESSION_ENGINE
相应地更改参数settings.py
from datetime import timedelta
from django.contrib.sessions.backends.file import SessionStore as FileSessionStore
class SessionStore(FileSessionStore):
def set_expiry(self, value):
""" force to convert to timedelta format """
if value and isinstance(value, int):
value = timedelta(seconds=value)
super().set_expiry(value=value)
注意:传递timedelta
或也datetime
可以set_expiry(value)
,但您需要处理datetime
object的序列化问题。