通过信号向 websocket 发送数据

Send data to websocket via signals

希望你们一切都好。我一直在尝试创建一个通知系统,通过来自数据库的 post_save 信号将消息推送到 websocket。我有一个创建通知的通知模型,我想在向适当的用户创建通知时推送通知,我们将不胜感激。

Signals.py

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
        }
    )

这就是我的 consumer.py 的样子

consumer.py

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")    


问题已通过使用以下代码在 post_save 相关模型上使用 consumers.py 和 signals.py 创建通知系统得到解决。

consumers.py

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)

models.py

@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
            )