Django - Урок 048. Как добавить статус онлайн на сайте

Auth, Django, Backend, Python

Долгое время не добавлял подобный функционал на сайте по той простой причине, что не знал, с какой бы стороны к этому подойти, поскольку хотелось бы обрабатывать данную информацию в одном единственном месте, а не в каждом View.

Со временем я начал модифицировать Backend классы для сайта и решение пришло само собой. Нужно было всего лишь модифицировать каждый бэкенд аутентификации, который используется на сайте. И переписать метод get_user, в котором будет сохраняться информация о последнем запросе пользователя к сайту. А статус онлайн можно сохранять последние 15 минут, потом статус будет оффлайн.

А дату последнего запроса можно хранить либо в профиле пользователя, который будет OneToOne моделью к пользователю, либо переопределить модель пользователя. Я выбрал вариант с переопределением модели пользователя.

my_auth

Создадим наш собственный модуль аутентификации my_auth, если вы его ещё не создали

python manage.py startapp my_auth

models.py

После чего переопределим модель пользователя

# -*- coding: utf-8 -*-

from django.contrib.auth.models import AbstractUser
from django.contrib.humanize.templatetags.humanize import naturaltime
from django.db import models
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _


class User(AbstractUser):

    last_online = models.DateTimeField(blank=True, null=True)

    # В данном методе проверяем, что дата последнего посещения не старше 15 минут
    def is_online(self):
        if self.last_online:
            return (timezone.now() - self.last_online) < timezone.timedelta(minutes=15)
        return False

    # Если пользователь посещал сайт не более 15 минут назад, 
    def get_online_info(self):
        if self.is_online():
            # то возвращаем информацию, что он онлайн
            return _('Online')
        if self.last_online:
            # иначе пишем сообщение о последнем посещении
            return _('Last visit {}').format(naturaltime(self.last_online))
            # Если вы только недавно добавили информацию о посещении пользователем сайта
            # то для некоторых пользователей инфомации о посещении может и не быть, вернём информацию, что последнее посещение неизвестно
        return _('Unknown')

backends.py

Далее напишем собственный бэкенд аутентификации, который будет заменять бэкенд Django.

# -*- coding: utf-8 -*-

from django.contrib.auth import get_user_model
from django.utils import timezone


class MyBackend:

    def get_user(self, user_id):
        try:
            user = get_user_model().objects.get(pk=user_id)
            user.last_online = timezone.now()  # При запросе пользователя выполним обновлении даты и времени последнего посещения
            user.save(update_fields=['last_online'])
            return user
        except get_user_model().DoesNotExist:
            return None

settings.py

Не забываем зарегистрировать наше приложение ...

INSTALLED_APPS = [
    'my_auth.apps.MyAuthConfig',
    ...
]

... и добавить бэкенд аутентификации

AUTHENTICATION_BACKENDS = (
    'my_auth.backends.MyBackend',
    'django.contrib.auth.backends.ModelBackend',
)

Заключение

Теперь при каждом запросе пользователя к сайту у вашего пользователя будет обновляться информация о его последнем посещении.

И вы сможете в шаблоне делать у пользовтелей в контенте, находится ли он онлайн или нет. Например так, чтобы добавить значок Online у аватарки

{% if user.is_online %}
    <div class="online"></div>
{% endif %}

или так отображать информацию о его онлайн статусе.

<span class="text-muted">{{ user_profile.get_online_info }}</span>

Возможный недостаток данного метода заключается в том, что пользователь может открыть страницу и ничего не делать целый час на ней.
Но в моём случае это не является проблемой, поскольку я каждую минуту вызываю проверку статусной информации у аутентифицированного пользователя, таким образом, пока страница пользователя остаётся открытой, каждую минуту обновляется его статус онлайн.

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.
- блог компании
Поддержать автора Donate

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
Ищу работу?
25,000.00 руб. - 30,000.00 руб.
Разработчик Qt/C++
Barnaul, Altai Krai, Russia

Для зарегистрированных пользователей на сайте присутствует минимальное количество рекламы

ЮА
17 сентября 2019 г. 8:51
Юлия Александрова

C++ - Тест 001. Первая программа и типы данных

  • Результат:33баллов,
  • Очки рейтинга-10
ЮА
17 сентября 2019 г. 8:36
Юлия Александрова

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат:10баллов,
  • Очки рейтинга-10
ВД
16 сентября 2019 г. 11:47
Виктор Дзенькив

C++ - Тест 002. Константы

  • Результат:75баллов,
  • Очки рейтинга2
Последние комментарии
17 сентября 2019 г. 6:07
Misha Lebedev

Кстати интересные темы нашёл тут https://emacsway.github.io/ru/django-framework/#django-models Может что полезного тоже Евгений найдёте
17 сентября 2019 г. 4:50
Misha Lebedev

Доброго времени суток. Спасибо за хороший ответ, У меня ситуация така что в галлереи будет несколько миллионов фотографий с фильтрами и тегами , и я опасаюсь за производительност . Это ос…
17 сентября 2019 г. 3:23
Евгений Легоцкой

Добрый день. Да, я тоже читал ту статью в своё время и согласен с тем, что внешние ключи гораздо лучше, чем GenericForeignKey. Выборки в ряде случае работают быстрее. Но лично мне про…
14 сентября 2019 г. 17:08
Misha Lebedev

Приветствую вас Евгений , давно наблюда за развитием вашего замечательного портала, много полезно тут нашел , переодически зачитываюсь. Теперь по сушеству, делаю портал и там идеально ложи…
10 сентября 2019 г. 16:38
Евгений Легоцкой

function view для модели Article и LikeDislike.LIKE будет выглядеть так def like(request, pk): obj = Article.objects.get(pk=pk) try: likedislike = LikeDislike.objects.get(cont…
Сейчас обсуждают на форуме
p
17 сентября 2019 г. 5:02
pstMem

Да, действительно нужно дебажить, по другому не словить исключение. Уже решил проблему, был выход за предел массива, не правильные входные данные, так что всегда проверяйте размер массива.
17 сентября 2019 г. 3:39
Евгений Легоцкой

Добрый день! На удалённом сервере вряд ли. Этот класс из core модуля, а удалённый сервер - это ещё и network модуль нужно подтягивать. Тут на удалэнном сервере нужно делать программу…
17 сентября 2019 г. 3:30
Евгений Легоцкой

Добрый день! Попробуйте toHex() А также создние QString с помощью from методов. Может быть QString::fromLatin1(). В документации на QString почти два десятка методов from, один из них…
m
16 сентября 2019 г. 13:54
mihamuz

Однозначно PostgreSql не ниже 10 ки.
R
16 сентября 2019 г. 7:09
RED_Spider

прочитайте https://doc.qt.io/archives/qt-5.11/osx-deployment.html QMAKE_POST_LINK += "~/Qt/5.12.0/clang_64/bin/macdeployqt $${TARGET}.app $$escape_expand( \\n\\t )"
EVILEG
О нас
Услуги
© EVILEG 2015-2019
Рекомендует хостинг TIMEWEB