L
Feb. 7, 2021, 12:50 a.m.

Не работает код на статус онлайн

Django

При попытке добавить код для статуса как встатье, я сталкнулся с проблемой, что он не записывает данные в бд(поля last_online NULL), такое ощущение, что бек просто не работает. Можете подсказать как это исправить?
Версия Django 3.1.6
Версия питона 3.8.2
Модель юзера

  1. from django.db import models
  2. from django.contrib.auth.models import User
  3. from PIL import Image
  4. from django.urls import reverse
  5. from django.contrib.humanize.templatetags.humanize import naturaltime
  6. from django.utils import timezone
  7.  
  8.  
  9. class Profile(models.Model):
  10. user = models.OneToOneField(User, on_delete=models.CASCADE)
  11. image = models.ImageField(default='default.jpg', upload_to='profile_pics')
  12. last_online = models.DateTimeField(blank=True, null=True)
  13.  
  14. def __str__(self):
  15. return f'{self.user.username} Profile'
  16.  
  17. # В данном методе проверяем, что дата последнего посещения не старше 15 минут
  18. def is_online(self):
  19. if self.last_online:
  20. return (timezone.now() - self.last_online) < timezone.timedelta(minutes=15)
  21. return False
  22.  
  23. def get_online_info(self):
  24. if self.is_online():
  25. return 'Онлайн'
  26. if self.last_online:
  27. return f'Последнее посещение: {naturaltime(self.last_online)}'
  28. else:
  29. return 'Не известно'

код MyBackend

  1. from django.contrib.auth import get_user_model
  2. from django.utils import timezone
  3. from django.contrib.auth.backends import BaseBackend
  4.  
  5.  
  6. class MyBackend(BaseBackend):
  7.  
  8. def get_user(self, user_id):
  9. try:
  10. user = get_user_model().objects.get(pk=user_id)
  11. user.last_online = timezone.now() # При запросе пользователя выполним обновлении
  12. # даты и времени последнего посещения
  13. user.save(update_fields=['last_online'])
  14. return user
  15. except get_user_model().DoesNotExist:
  16. return None

файл settings

  1. AUTHENTICATION_BACKENDS = (
  2. 'users.backends.MyBackend',
  3. 'django.contrib.auth.backends.ModelBackend',
  4. )

код темплейта

  1. <span class="caption-1">Статус</span>
  2. <span class="body-2">{{ user.get_online_info }}</span>
2
The question is asked by the articleDjango - Tutorial 048. How to add online status to a site

Do you like it? Share on social networks!

6
Илья Чичак
  • Feb. 7, 2021, 2:09 a.m.

auth_backend - это про другое. Попробуйте сделать это через middleware?

    L
    • Feb. 7, 2021, 2:14 a.m.

    пишет такое

    1. TypeError: MyBackend() takes no arguments
    1. MIDDLEWARE = [
    2. 'django.middleware.security.SecurityMiddleware',
    3. 'django.contrib.sessions.middleware.SessionMiddleware',
    4. 'django.middleware.common.CommonMiddleware',
    5. 'django.middleware.csrf.CsrfViewMiddleware',
    6. 'django.contrib.auth.middleware.AuthenticationMiddleware',
    7. 'django.contrib.messages.middleware.MessageMiddleware',
    8. 'django.middleware.clickjacking.XFrameOptionsMiddleware',
    9. 'users.backends.MyBackend',
    10. 'django.contrib.auth.middleware.AuthenticationMiddleware',
    11. 'blacklist.middleware.blacklist_middleware',
    12. ]
      Илья Чичак
      • Feb. 7, 2021, 2:30 a.m.

      так, я поторопился. Надо разбираться
      если вы делаете через auth_backend - last_online будет проставляться только в момент логина. Если сделать через middleware, оно будет обновляться каждый раз,когда пользователь будет делать что-либо.
      Тоесть, в первом случае, пользователь может авторизоваться и пользоваться сайтом час-два,но спустя 15 минут будет показано, что он оффлайн. А если нет протухания сессии, пользователь может и на следующий день вернуться, а показано будет, что он оффлайн.
      Во втором случае, пока он ходил по ссылкам и выполняет запросы - он будет отображаться, как онлайн. Но возрастет нагрузка на базу.

      если нагрузка по боку, я бы сделал такую middleware:

      1. class LastOnlineMiddleware:
      2. def __init__(self, get_response):
      3. self.get_response = get_response
      4.  
      5. def __call__(self, request):
      6. if request.user.is_authenticated:
      7. get_user_model().filter(id=request.user.id).update(last_online=timezone.now())
      8. response = self.get_response(request)
      9. return response

      так одним запросом будет обновляться его поле а дальше запросы будут выполняться, как выполнялись

        L
        • Feb. 7, 2021, 2:49 a.m.

        На нагрузку без разницы, и для меня ваш вариант подходит, но к сожалению выбивает в ошибку.

        1. Internal Server Error: /
        2. Traceback (most recent call last):
        3. File "C:\Python38\lib\site-packages\django\core\handlers\exception.py", line 47, in inner
        4. response = get_response(request)
        5. File "C:\Users\Livis\PycharmProjects\djangosite\users\backends.py", line 25, in __call__
        6. get_user_model().filter(id=request.user.id).update(last_online=timezone.now())
        7. AttributeError: type object 'User' has no attribute 'filter'

        Я заменил класс MyBackend, на ваш предложенный

        1. class LastOnlineMiddleware:
        2. def __init__(self, get_response):
        3. self.get_response = get_response
        4.  
        5. def __call__(self, request):
        6. if request.user.is_authenticated:
        7. get_user_model().filter(id=request.user.id).update(last_online=timezone.now())
        8. response = self.get_response(request)
        9. return response
        1. MIDDLEWARE = [
        2. 'django.middleware.security.SecurityMiddleware',
        3. 'django.contrib.sessions.middleware.SessionMiddleware',
        4. 'django.middleware.common.CommonMiddleware',
        5. 'django.middleware.csrf.CsrfViewMiddleware',
        6. 'django.contrib.auth.middleware.AuthenticationMiddleware',
        7. 'django.contrib.messages.middleware.MessageMiddleware',
        8. 'django.middleware.clickjacking.XFrameOptionsMiddleware',
        9. 'users.backends.LastOnlineMiddleware',
        10. 'django.contrib.auth.middleware.AuthenticationMiddleware',
        11. 'blacklist.middleware.blacklist_middleware',
        12. ]
          Илья Чичак
          • Feb. 7, 2021, 3:51 a.m.
          • The answer was marked as a solution.

          опечатался:
          get_user_model().filter(id=request.user.id).update(last_online=timezone.now())
          поменять на:
          get_user_model().objects.filter(id=request.user.id).update(last_online=timezone.now())

            L
            • Feb. 7, 2021, 6:17 a.m.

            Спасибо за уделенное время, всё работает

              Comments

              Only authorized users can post comments.
              Please, Log in or Sign up
              • Last comments
              • AK
                April 1, 2025, 11:41 a.m.
                Добрый день. В данный момент работаю над проектом, где необходимо выводить звук из программы в определенное аудиоустройство (колонки, наушники, виртуальный кабель и т.д). Пишу на Qt5.12.12 поско…
              • Evgenii Legotckoi
                March 9, 2025, 9:02 p.m.
                К сожалению, я этого подсказать не могу, поскольку у меня нет необходимости в обходе блокировок и т.д. Поэтому я и не задавался решением этой проблемы. Ну выглядит так, что вам действитель…
              • VP
                March 9, 2025, 4:14 p.m.
                Здравствуйте! Я устанавливал Qt6 из исходников а также Qt Creator по отдельности. Все компоненты, связанные с разработкой для Android, установлены. Кроме одного... Когда пытаюсь скомпилиров…
              • ИМ
                Nov. 22, 2024, 9:51 p.m.
                Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
              • Evgenii Legotckoi
                Oct. 31, 2024, 11:37 p.m.
                Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup