I am new to Django channels , i followed the documentation tutorial and i made a Django chat room , so far i can send and recieve messages , but the probleme here the sender is unknown , i tried to send the username but its not working , i get the username printed in the server but in the front i get the actual login username?? i am confused ?
consumer.py :
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.room_name = self.scope['url_route']['kwargs']['room_name']
self.room_group_name = 'chat_%s' % self.room_name
self.user = self.scope["user"]
# Join room group
await self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
await self.accept()
async def disconnect(self, close_code):
# Leave room group
await self.channel_layer.group_discard(
self.room_group_name,
self.channel_name
)
# Receive message from WebSocket
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json['message']
# Send message to room group
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'chat_message',
'message': message
}
)
# Receive message from room group
async def chat_message(self, event):
message = event['message']
print(self.user.username)
# Send message to WebSocket
await self.send(text_data=json.dumps({
'message': message,
'username' : str(self.user.username),
}))
room.html :
<!-- chat/templates/chat/room.html -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>Chat Room</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<div style="width:800px; margin:0 auto;">username :
<a id="username" href="">{{ user.get_username }}</a>
<textarea id="chat-log" cols="100" rows="20"></textarea><br/>
<input id="chat-message-input" type="text" size="75"/><br/>
<input id="chat-message-submit" type="button" value="Send"/>
</div>
</body>
<script>
var roomName = {{ room_name_json }};
var chatSocket = new WebSocket(
'ws://' + window.location.host +
'/ws/chat/' + roomName + '/');
chatSocket.onmessage = function(e) {
var data = JSON.parse(e.data);
var message = data['message'];
console.log(e.data)
document.querySelector('#chat-log').value += ( message + '\n');
};
chatSocket.onclose = function(e) {
console.error('Chat socket closed unexpectedly');
};
document.querySelector('#chat-message-input').focus();
document.querySelector('#chat-message-input').onkeyup = function(e) {
if (e.keyCode === 13) { // enter, return
document.querySelector('#chat-message-submit').click();
}
};
document.querySelector('#chat-message-submit').onclick = function(e) {
var messageInputDom = document.querySelector('#chat-message-input');
var message = messageInputDom.value;
chatSocket.send(JSON.stringify({
'message': message
}));
messageInputDom.value = '';
};
</script>
</html>
When the user connects, he gets a separate instance of the ChatConsumer
and you set the self.user
. If he receives a message from another channel, the self.user
does not change, it is still the one you set for him. So to show the username of the sender, you have to send it along with the message like this:
...
# Receive message from WebSocket
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json['message']
# Send message to room group
await self.channel_layer.group_send(
self.room_group_name,
{
'type': 'chat_message',
'message': message,
'username': self.user.username
}
)
# Receive message from room group
async def chat_message(self, event):
message = event['message']
username = event['username']
print(username)
# Send message to WebSocket
await self.send(text_data=json.dumps({
'message': message,
'username' : username,
}))
It is important to note that separate instances of ChatConsumer run the methods receive
and chat_message
, hence the self.user
in those methods are different. While the receive
method is executed in the sender's channel, the chat_message
method is executed in the channels of the receivers which will also include the sender in this case, since he is in the same group as the receivers.
For example, to see if the message you received was sent by you, you could do something like this in the chat_message
method:
if event['username'] == self.user.username:
...