Django База [2023]: Функционал статуса пользователя (онлайн/оффлайн) в Django с кэшированием #40
Один из способов добавления статуса пользователей основывается на использовании Middleware, который позволяет обрабатывать запросы перед тем, как они будут обработаны во view. Middleware позволяет работать со всеми запросами, и поэтому он является отличным местом для реализации этого функционала.
Если вы хотите выразить благодарность автору сайта, статей и курса по Django, вы можете сделать это по ссылке ниже:
Мы будем использовать также систему кэширования, чтобы наше Django приложение не нагружалось.
Добавим файловую систему кэширования
Пока мы обойдемся фаловой системой кэширования, а в следующих уроках мы познакомимся с Redis кэшированием, поэтому в конфигурационный файл settings.py добавим следующий код в любое место:
CACHES = {
'default': {
'BACKEND': 'django.core.cache.backends.filebased.FileBasedCache',
'LOCATION': (BASE_DIR / 'cache'),
}
}
Создадим middleware с необходимым функционалом
Ниже приведен код middleware.py, который добавляет функционал статуса пользователей в приложение system:
from django.contrib.auth.models import User
from django.core.cache import cache
from django.utils import timezone
from django.utils.deprecation import MiddlewareMixin
class ActiveUserMiddleware(MiddlewareMixin):
def process_request(self, request):
if request.user.is_authenticated and request.session.session_key:
cache_key = f'last-seen-{request.user.id}'
last_login = cache.get(cache_key)
if not last_login:
User.objects.filter(id=request.user.id).update(last_login=timezone.now())
# Устанавливаем кэширование на 300 секунд с текущей датой по ключу last-seen-id-пользователя
cache.set(cache_key, timezone.now(), 300)
Этот код представляет собой middleware-класс ActiveUserMiddleware, который используется для обновления статуса "онлайн" пользователя в Django с помощью кэширования.
Middleware-класс ActiveUserMiddleware определяет метод process_request()
, который вызывается для каждого входящего запроса. В этом методе проверяется, авторизован ли пользователь, и имеет ли его сессия уникальный идентификатор session_key.
Если пользователь авторизован и имеет уникальный session_key, то обновляется его статус "последний раз в сети" с помощью метода cache.set()
и сохраняется в кэше на время 300 секунд (можем установить любое значение).
Если в кэше нет записи для пользователя, то его последнее время входа в систему обновляется на текущее время с помощью метода User.objects.filter().update()
, и время записывается в кэш.
Добавим этот middleware в конфигурационный файл проекта для его выполнения:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'debug_toolbar.middleware.DebugToolbarMiddleware',
'modules.system.middleware.ActiveUserMiddleware',
]
Функция is_online() в модели профиля
В models.py, в модели Profile, добавляется метод is_online()
, который проверяет, был ли пользователь онлайн в течение последних 5 минут:
from django.db import models
from django.contrib.auth.models import User
from django.utils import timezone
from django.core.cache import cache
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
slug = models.SlugField(verbose_name='URL', max_length=255, blank=True, unique=True)
# Другие поля...
# Другие методы...
def is_online(self):
last_seen = cache.get(f'last-seen-{self.user.id}')
if last_seen is not None and timezone.now() < last_seen + timezone.timedelta(seconds=300):
return True
return False
Вывод статуса в профиле пользователя
Переходим в наш html шаблон профиля пользователя (templates/system/profile_detail.html) и добавляем следующую строку в шаблон:
{% extends 'main.html' %}
{% block content %}
<div class="card border-0">
<div class="card-body">
<div class="row">
<div class="col-md-3">
<figure>
<img src="{{ profile.avatar.url }}" class="img-fluid rounded-0" alt="{{ profile }}">
</figure>
</div>
<div class="col-md-9">
<h5 class="card-title">
{{ profile }}
</h5>
<div class="card-text">
<ul>
<li>Никнейм: {{ profile.user.username }}</li>
{% if profile.user.get_full_name %} <li>Имя и фамилия: {{ profile.user.get_full_name }}</li> {% endif %}
<li>Заходил: {{ profile.user.last_login }} | {% if profile.is_online %}Онлайн{% else %}Не в сети{% endif %}</li>
<li>Дата рождения: {{ profile.birth_date }}</li>
<li>О себе: {{ profile.bio }}</li>
</ul>
{% if request.user == profile.user %} <a href="{% url 'profile_edit' %}" class="btn btn-sm btn-primary">Редактировать профиль</a> {% endif %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}
Проверка работы статуса
Таким образом мы создали оптимизированную систему статусов пользователей, используя систему кэширования. Вы можете использовать любую систему кэширования, рекомендуем: redis.