Уведомления, не подлежащие щелчку, после «чтения»: ошибка «ID-уведомления не определен» - PullRequest
1 голос
/ 03 мая 2019

Я использую JQuery / JS с Django Channels WebSockets для настройки уведомлений в режиме реального времени для сообщений чата.

Когда у пользователя есть какие-либо Notification объекты с nofication_read=False, они отображаются на панели навигации с кодом ниже.

{{ notification|length }} отображает количество Notification объектов с nofication_read=False.

navbar.html

<li id="notification_li" class="nav-item">
  <a class="nav-link" href="#" id="notificationLink">
    <span id="notification_id{{notification_id}}">{{ notification|length }}</span>
  <div id="notificationContainer">
    <div id="notificationTitle">Notifications</div>
    <div id="notificationsBody" class="notifications">
      {% for notifications in notification|slice:"0:10" %}
        <span id="notification-{{notification.id}}">
          {{ notifications.notification_chat.message }}
          via {{ notifications.notification_chat.user }}
          at {{ notifications.notification_chat.timestamp }}
        </span>
      {% endfor %}

Я знаю, что сейчас это не в реальном времени.

Но проблема в том, что когда пользователь обновляет страницу и нажимает на красный значок span id=notification_id, чтобы отобразить список непрочитанных уведомлений, данные отправляются через веб-сокет (JSON.stringify) как "type": "notification_read", который вызывает if message_type == "notification_read": команда в consumers.y, которая помечает их как nofication_read=True в базе данных.

Когда пользователь обновляет страницу, красный значок больше не появляется, и когда он пытается нажать на фоновую ссылку, он не активируется с ошибкой в ​​консоли браузера

Uncaught ReferenceError: notification_id is not defined

Как только они получают другое уведомление и страница обновляется, она, очевидно, снова становится активной.

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

consumers.py

class ChatConsumer(AsyncConsumer):
    ...
    async def websocket_receive(self, event):
        message_type = json.loads(event.get('text','{}')).get('type')
        if message_type == "notification_read":
            user = self.scope['user']
            username = user.username if user.is_authenticated else 'default'
            # Update the notification read status flag in Notification model.
            notification = Notification.objects.filter(notification_user=user).update(notification_read=True)
            print("notification read")
            return 

front_text = event.get('text', None)
        if front_text is not None:
            loaded_dict_data = json.loads(front_text)
            msg =  loaded_dict_data.get('message')
            user = self.scope['user']
            username = user.username if user.is_authenticated else 'default'
            notification_id = 'default'
            myResponse = {
                'message': msg,
                'username': username,
                'notification': notification_id,
            }
   ...
        await self.create_chat_message(user, msg)
        other_user = self.scope['url_route']['kwargs']['username']
        other_user = User.objects.get(username=other_user)
        await self.create_notification(other_user, msg)
       ...
@database_sync_to_async
def create_chat_message(self, me, msg):
    thread_obj = self.thread_obj
    return ChatMessage.objects.create(thread=thread_obj, user=me, message=msg)

@database_sync_to_async
def create_notification(self, other_user, msg):
    last_chat = ChatMessage.objects.latest('id')
    created_notification = Notification.objects.create(notification_user=other_user, notification_chat=last_chat)
    return created_notification

context_processors.py

def notification(request):
    if request.user.is_authenticated:
        notification = Notification.objects.filter(notification_user=request.user, notification_read=False)
        return {
        'notification':notification,
    return Notification.objects.none()

base.html

 <script>
    $(document).ready(function() {
     $("#notificationLink").click(function() {
        var data = {
          "type": "notification_read",
          "username": username,
          "notification_id": notification_id,
        }
        socket.send(JSON.stringify(data));

        $("#notificationContainer").fadeToggle(300);
        $("#notification_id").fadeOut("slow");
        return false;
      });
...
var incomingMsg = $('.incoming_msg')

socket.onmessage = function(e) {
      console.log("message", e)
      var chatDataMsg = JSON.parse(e.data)
      incomingMsg.append('<li>' + chatDataMsg.message + ' from ' + chatDataMsg.username + '</li>')
    }

1 Ответ

2 голосов
/ 03 мая 2019

до "notification_id": notification_id вы должны определить notification_id, но в вашем случае вам нужно сделать это по циклу, вы можете попробовать:

 $("#notificationLink").click(function() {

   $('span[id^="notification-"]').each(function(){
        var notification_id = $(this).attr('id').substring(13)
        var data = {
          "type": "notification_read",
          "username": username,
          "notification_id": notification_id,
        }
        socket.send(JSON.stringify(data));
    });

    $("#notificationContainer").fadeToggle(300);
    $("#notification_id").fadeOut("slow");
    return false;
  })

Я надеюсь, что в вашем шаблоне у вас уже есть что-то вроде:

var username = '{{ request.user.username }}'

по вашему текущему коду на бэкэнде вам не нужен notification_id, поэтому вы можете просто удалить его:

 $("#notificationLink").click(function() {
    var data = {
      "type": "notification_read",
      "username": username,
    }
    socket.send(JSON.stringify(data));

    $("#notificationContainer").fadeToggle(300);
    $("#notification_id").fadeOut("slow");
    return false;
  });
...