![Django База [2023]: Функционал статуса пользователя (онлайн/оффлайн) в Django с кэшированием #40](/_next/image?url=https%3A%2F%2Fproghunter.ru%2Fmedia%2Fimages%2Fthumbnails%2F2023%2F02%2F27%2Fimage-d07a47f573.png&w=3840&q=75)
Django Django База [2023]: Функционал статуса пользователя (онлайн/оффлайн) в Django с кэшированием #40
Один из способов добавления статуса пользователей основывается на использовании Middleware, который позволяет обрабатывать запросы перед тем, как они будут обработаны во view. Middleware позволяет работать со всеми запросами, и поэтому он является отличным местом для реализации этого функционала. Мы будем использовать также систему кэширования, чтобы наше 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 %}
Проверка работы статуса
![Django База [2023]: Функционал статуса пользователя (онлайн/оффлайн) в Django с кэшированием #40](/_next/image?url=https%3A%2F%2Fproghunter.ru%2Fmedia%2Fimages%2Fuploads%2F2023%2F02%2F27%2Fdfdb1761c2-uploaded-image.jpg&w=3840&q=75)
![Django База [2023]: Функционал статуса пользователя (онлайн/оффлайн) в Django с кэшированием #40](/_next/image?url=https%3A%2F%2Fproghunter.ru%2Fmedia%2Fimages%2Fuploads%2F2023%2F02%2F27%2Ffa00152678-uploaded-image.jpg&w=3840&q=75)
![Django База [2023]: Функционал статуса пользователя (онлайн/оффлайн) в Django с кэшированием #40](/_next/image?url=https%3A%2F%2Fproghunter.ru%2Fmedia%2Fimages%2Fuploads%2F2023%2F02%2F27%2Fbd983b553b-uploaded-image.jpg&w=3840&q=75)
![Django База [2023]: Функционал статуса пользователя (онлайн/оффлайн) в Django с кэшированием #40](/_next/image?url=https%3A%2F%2Fproghunter.ru%2Fmedia%2Fimages%2Fuploads%2F2023%2F02%2F27%2Fc195f66063-uploaded-image.jpg&w=3840&q=75)
![Django База [2023]: Функционал статуса пользователя (онлайн/оффлайн) в Django с кэшированием #40](/_next/image?url=https%3A%2F%2Fproghunter.ru%2Fmedia%2Fimages%2Fuploads%2F2023%2F02%2F27%2F4e26954a09-uploaded-image.jpg&w=3840&q=75)
![Django База [2023]: Функционал статуса пользователя (онлайн/оффлайн) в Django с кэшированием #40](/_next/image?url=https%3A%2F%2Fproghunter.ru%2Fmedia%2Fimages%2Fuploads%2F2023%2F02%2F27%2Fe3a3f151ec-uploaded-image.jpg&w=3840&q=75)
Таким образом мы создали оптимизированную систему статусов пользователей, используя систему кэширования. Вы можете использовать любую систему кэширования, рекомендуем: redis.