I hope you all are doing well. I have been trying to create a notification system that will push messages to websocket via post_save signals from database. I have a Notification model that creates notification and I want to push notifications whenever a notification is created to the appropriate user, any help in it would be much appreciated.
def send_message(event):
'''
Call back function to send message to the browser
'''
message = event['text']
channel_layer = channels.layers.get_channel_layer()
# Send message to WebSocket
print("Sending message to websocket")
async_to_sync(channel_layer.send)(text_data=json.dumps(
message
))
@receiver(post_save,sender=Notification)
def notification_handler(sender,instance,created,*args,**kwargs):
message={
'text':instance.text
}
print(message)
user=str(instance.to.pk)
groupname=f"user_{user}"
channel_layer = channels.layers.get_channel_layer()
async_to_sync(channel_layer.group_send)(
groupname,
{
'type': 'send_message',
'text': message
}
)
This is how my consumer.py looks like
class NotificationConsumer(AsyncWebsocketConsumer):
async def websocket_connect(self,event):
print("connected",event)
self.channel_layer=channels.layers.get_channel_layer()
self.user = self.scope['url_route']['kwargs']['user_id']
self.group_name =f"user_{self.user}"
await self.channel_layer.group_add(
self.group_name,
self.channel_name
)
await self.accept()
async def websocket_disconnect(self,event):
print(event,"closed")
The issue was resolved by creating the notifications system with the following code with consumers.py and signals.py on post_save of concerned models.
class NotificationConsumer(AsyncWebsocketConsumer):
async def websocket_connect(self,event):
print("connected",event)
self.channel_layer=channels.layers.get_channel_layer()
self.user = self.scope['url_route']['kwargs']['user_id']
self.group_name =f"user_{self.user}"
print(self.group_name)
await self.channel_layer.group_add(
self.group_name,
self.channel_name
)
await self.accept()
user=self.scope['user']
unread_notifications= await self.get_unread_notifications(user)
unread_notifications['notification_type']="group"
await self.channel_layer.group_send(
self.group_name,
{
'type': 'send_notification',
'text': unread_notifications
}
)
#To fetch unread notifications which have been recorded while the user was offline
@staticmethod
@receiver(post_save,sender=Notification)
def notification_handler(sender,instance,created,*args,**kwargs):
if instance.read !=1:
message={
'notification_type':"single",
'text':instance.text,
'id':instance.pk_object,
"type":instance.Type,
"timestamp":str(instance.timestamp),
"by":ProfileSerializer(instance.by).data
}
print("Inside the notification trigger",message)
user=str(instance.to.user.pk)
groupname=f"user_{user}"
channel_layer = channels.layers.get_channel_layer()
async_to_sync(channel_layer.group_send)(
groupname,
{
'type': 'send_notification',
'text': message
}
)
async def send_notification(self, event):
print("inside send notification")
await self.send(text_data=json.dumps({
'type': 'websocket.send',
'text': event['text']
}))
@database_sync_to_async
def get_unread_notifications(self, user):
return Notification.objects.get_unread(user)
@receiver(post_save,sender=Connect)
def connect_handler(sender,instance,created,*args,**kwargs):
from django.apps import apps
Notification= apps.get_model("notifications","Notification")
if created and instance.confirmed == 0:
print("inside trigger")
notification=Notification.objects.create(
to=instance.user2,
Type="connection",
text=f"{instance.user1} sent you a connection request",
by=instance.user1,
pk_object=instance.user1.pk
)
@receiver(post_save,sender=Like)
def like_handler(sender,instance,created,*args,**kwargs):
from django.apps import apps
Notification= apps.get_model("notifications","Notification")
if created:
if instance.idea != None:
changed=instance.idea
changed_type="Idea"
object_id=instance.idea.pk
element=instance.idea
else:
changed=instance.post
changed_type="Post"
object_id=instance.post.pk
element =instance.post
if instance.Liked_by != element.posted_by:
notification=Notification.objects.create(
to=changed.posted_by,
Type=changed_type,
text=f"{instance.Liked_by.user.username} Liked your {changed_type}",
by=instance.Liked_by,
pk_object=object_id
)