Reputation: 1226
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
Upvotes: 4
Views: 2592
Reputation: 11
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).
Upvotes: 0
Reputation: 2408
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)
Upvotes: 2