4

I'm trying to send a notification to the user using websockets, on a particular event. I have the following model receiver which triggers a websocket method:

@receiver(pre_save, sender=settings.AUTH_USER_MODEL)
def create_auth_token(sender, instance=None, created=False, update_fields=None, **kwargs):
    if update_fields:
        if 'pan_number_verified' in update_fields and instance.pan_number_verified is True:
            notification = Notification.objects.create(message='Your PAN Number has been verified...Head on to '
                                                               'creating a campaign right away.', user=instance)
            channel_layer = get_channel_layer()
            async_to_sync(channel_layer.group_send)("notification_%s" % instance.id, {
                "type": "app_consumer.notification_message",
                "message": str(notification.id)
            })

Here is my app consumer:

class AppConsumer(WebsocketConsumer):
    def connect(self):
        self.room_name = self.scope['url_route']['kwargs']['user_id']
        self.room_group_name = 'notification_%s' % self.room_name
        async_to_sync(self.channel_layer.group_add)(
            self.room_group_name,
            self.channel_name
        )
        self.accept()

    def disconnect(self, close_code):
        async_to_sync(self.channel_layer.group_discard)(
            self.room_group_name,
            self.channel_name
        )

    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']

        async_to_sync(self.channel_layer.group_send)(
            self.room_group_name,
            {
                'type': 'app_consumer.notification_message',
                'message': message
            }
        )

    def notification_message(self, event):
        message = event['message']

        self.send(text_data=json.dumps({
            'message': message
        }))

But I get the following error message:

Exception inside application: No handler for message type app_consumer.notification_message

File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/channels/consumer.py", line 59, in call [receive, self.channel_receive], self.dispatch

File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/channels/utils.py", line 51, in await_many_dispatch await dispatch(result)

File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/asgiref/sync.py", line 244, in call return await asyncio.wait_for(future, timeout=None)

File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/tasks.py", line 414, in wait_for return await fut

File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/concurrent/futures/thread.py", line 57, in run result = self.fn(*self.args, **self.kwargs)

File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/channels/db.py", line 14, in thread_handler return super().thread_handler(loop, *args, **kwargs)

File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/asgiref/sync.py", line 277, in thread_handler return func(*args, **kwargs)

File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/channels/consumer.py", line 107, in dispatch raise ValueError("No handler for message type %s" % message["type"])

No handler for message type app_consumer.notification_message

2 Answers 2

2

You issue here is the name of your notification_message handler method.

Channels expects it to be named app_consumer_notification_message.

Channels replaces the . in message types with _ when looking for a message handling method.

(the prefix in the message type is not used for routing just the group name)

Sign up to request clarification or add additional context in comments.

Comments

0

The error you're seeing occurs because the message you're sending via channel_layer.group_send is missing a type attribute. In Django Channels, the message must include a type so that it knows how to handle the incoming message.

To fix this, you need to add a type to the message you're sending in the receive method. Here’s how you can modify your code:

def receive(self, text_data):
    text_data_json = json.loads(text_data)
    message = text_data_json["message"]
    async_to_sync(self.channel_layer.group_send)(
        self.room_group_name, {
            "type": "chat_message",  
            "message": message,
            "user": "user"
        }
    )

Then, you'll need to define a method to handle this message type. For example, you can add a chat_message method like this:

def chat_message(self, event):
    message = event["message"]
    user = event["user"]
    self.send(text_data=json.dumps({
        "message": message,
        "user": user
    }))

This will ensure that Django Channels can properly process and route the message based on the type you’ve specified (chat_message in this case).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.