我使用Django和Redis作为会话引擎(也是芹菜,但这是另一回事)。它运行得很好,我可以看到速度的提高。
SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'
我有一个脚本,每分钟运行一次,通过一些方法检查活动用户,如果用户在最近一分钟内没有活动,则会话被删除。这样做是为了满足客户的跟踪需求。
这个脚本工作完美,直到我切换到Redis作为会话引擎。会话确实从DB中删除,但不会从Redis中删除。我没有使用任何Django内置的方法,而是使用我自己的函数:
def clean_sessions():
stored_sessions = Session.objects.all()
active_users = active_users(minutes=1)
active_users_ids = [user.id for user in active_users]
for session in stored_sessions:
session_uid = session.get_decoded().get('_auth_user_id')
if not session_uid:
session.delete()
continue
if session_uid not in active_users_ids:
user = User.objects.get(pk=session_uid)
## some code between ##
session.delete()
我的问题是,我如何从缓存中删除会话,以便用户实际注销?
这不是很直接,但我能够解决它。我从我的clean_sessions()文件中导入了它:
from importlib import import_module
from django.conf import settings
然后,在函数内部,我加载SessionStore对象:
SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
从那里,很容易删除会话,留下这样的方法:
def clean_sessions():
stored_sessions = Session.objects.all()
active_users = Request.objects.active_users(seconds=15)
active_users_ids = [user.id for user in active_users]
for session in stored_sessions:
SessionStore = import_module(settings.SESSION_ENGINE).SessionStore
s = SessionStore(session_key=session.session_key)
session_uid = session.get_decoded().get('_auth_user_id')
if not session_uid:
s.delete()
continue
if session_uid not in active_users_ids:
## some code ##
s.delete()
从你正在使用的任何会话引擎中加载正确的SessionStore是非常重要的,否则它将无法从两个地方(DB和缓存)删除它。
如果其他人需要清除所有会话数据(例如在测试期间)取决于后端在这个例子中,Redis和数据库:
from django.conf import settings
from django_redis import get_redis_connection
from django.contrib.sessions.models import Session
REDIS = "django.contrib.sessions.backends.cache"
DATABASE = "django.contrib.sessions.backends.db"
REDIS_AND_DATABASE = "django.contrib.sessions.backends.cached_db"
def clear_all_session_data_globally():
"""
This will log out every user instantly and delete whatever they were working on, use with caution
:return:
"""
if settings.SESSION_ENGINE in [REDIS, REDIS_AND_DATABASE]:
# Warning this deletes everything from your cache, not just session data
get_redis_connection(getattr(settings, 'SESSION_CACHE_ALIAS', 'default')).flushall()
if settings.SESSION_ENGINE in [DATABASE, REDIS_AND_DATABASE]:
Session.objects.all().delete()