In my Django Channels 2.1.2
chat application, I have a Notification
model that gives users notifications of unread messages (using JQuery).
class Notification(models.Model):
notification_user = models.ForeignKey(User, on_delete=models.CASCADE)
notification_chat = models.ForeignKey(ChatMessage, on_delete=models.CASCADE)
notification_read = models.BooleanField(default=False)
I need to save an instance of the Notification model each time a message is received through the websocket (taking in chat and user as args).
That instance will then be used to populate the notification center with unread notifications. When a user clicks on the red icon, the notification_read
method will be triggered in consumers.py
async def websocket_receive(self, event):
# when a message is recieved from the websocket
print("receive", event)
message_type = json.loads(event.get('text','{}')).get('type')
print(message_type)
if message_type == "notification_read":
# Update the notification read status flag in Notification model.
notification_id = '????'
notification = Notification.objects.get(id=notification_id)
notification.notification_read = True
notification.save() #commit to DB
print("notification read")
return
This currently doesn't work because I don't have notification_id
because notifications aren't being saved to the DB. I am unsure of how to write a method to do this each time a message is received over the websocket.
My code is below.
consumers.py
class ChatConsumer(AsyncConsumer):
async def websocket_connect(self, event):
print('connected', event)
other_user = self.scope['url_route']['kwargs']['username']
me = self.scope['user']
#print(other_user, me)
thread_obj = await self.get_thread(me, other_user)
self.thread_obj = thread_obj
chat_room = f"thread_{thread_obj.id}"
self.chat_room = chat_room
# below creates the chatroom
await self.channel_layer.group_add(
chat_room,
self.channel_name
)
await self.send({
"type": "websocket.accept"
})
async def websocket_receive(self, event):
# when a message is recieved from the websocket
print("receive", event)
message_type = json.loads(event.get('text','{}')).get('type')
print(message_type)
if message_type == "notification_read":
# Update the notification read status flag in Notification model.
notification_id = 'chat_message'
notification = Notification.objects.get(id=notification_id)
notification.notification_read = True
notification.save() #commit to DB
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 = 'notification'
myResponse = {
'message': msg,
'username': username,
'notification': notification_id,
}
await self.create_chat_message(user, msg)
# broadcasts the message event to be sent, the group send layer
# triggers the chat_message function for all of the group (chat_room)
await self.channel_layer.group_send(
self.chat_room,
{
'type': 'chat_message',
'text': json.dumps(myResponse)
}
)
# chat_method is a custom method name that we made
async def chat_message(self, event):
# sends the actual message
await self.send({
'type': 'websocket.send',
'text': event['text']
})
async def websocket_disconnect(self, event):
# when the socket disconnects
print('disconnected', event)
@database_sync_to_async
def get_thread(self, user, other_username):
return Thread.objects.get_or_new(user, other_username)[0]
@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)
Solved by adding this function to consumers.py underneath def create_chat_message
@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
And also adding
other_user = self.scope['url_route']['kwargs']['username']
other_user = User.objects.get(username=other_user)
await self.create_notification(other_user, msg)
after
await self.create_chat_message(user, msg)