Удаление сеансов из Redis (Джанго)

Я использую Django и Redis в качестве движка сессии (также Celery, но это нечто другое). Он отлично работает, и я вижу улучшение скорости.

SESSION_ENGINE = 'django.contrib.sessions.backends.cached_db'

У меня есть скрипт, который запускается каждую минуту для проверки активных пользователей с помощью некоторых методов, и если пользователь не был активным в последнюю минуту, то сеанс удаляется. Это сделано для отслеживания потребностей клиентов.

Этот скрипт работал отлично, пока я не переключился на Redis в качестве движка сессии. Сессия действительно удаляется из БД, но не из 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()

У меня вопрос, как мне также удалить сеанс из кэша, чтобы пользователь действительно вышел из системы?

1 ответ

Решение

Это было не очень просто, но я смог это исправить. Я импортировал это из файла, который у меня есть 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 из любого механизма сессий, который вы используете, иначе он не сможет удалить его из обоих мест (БД и кеш).

В случае, если кому-то это понадобится для очистки всех данных сеанса (например, во время тестов) в зависимости от серверной части. В этом случае 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]:
        get_redis_connection("default").flushall()

    if settings.SESSION_ENGINE in [DATABASE, REDIS_AND_DATABASE]:
        Session.objects.all().delete()
Другие вопросы по тегам