Я использую 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>')
}