Javascript&;Django频道:窗口关闭时聊天应用程序注销通知
我正在编写一个带有Javascript和Django频道的聊天应用程序。我正在尝试获取“用户已离开聊天室”消息,以便在窗口关闭时发送,也可能在websocket关闭时发送。我不确定websocket是否关闭得太快,但我目前拥有的代码不起作用。我可能应该在聊天消费者的disconnect函数中定义。我不确定这些东西的处理顺序 JavascriptJavascript&;Django频道:窗口关闭时聊天应用程序注销通知,javascript,python,django,chat,django-channels,Javascript,Python,Django,Chat,Django Channels,我正在编写一个带有Javascript和Django频道的聊天应用程序。我正在尝试获取“用户已离开聊天室”消息,以便在窗口关闭时发送,也可能在websocket关闭时发送。我不确定websocket是否关闭得太快,但我目前拥有的代码不起作用。我可能应该在聊天消费者的disconnect函数中定义。我不确定这些东西的处理顺序 Javascript // Declare variables var userName; var currentZone = new Date().toTi
// Declare variables
var userName;
var currentZone = new Date().toTimeString().slice(17);
// var roomName = {{ room_name_json }};
document.getElementById("chatname").innerHTML = roomName;
// Create Websocket
var chatSocket = new ReconnectingWebSocket(
'ws://' + window.location.host +
'/ws/chat/' + roomName + '/');
// Send message
chatSocket.onmessage = function(e) {
var data = JSON.parse(e.data);
var message = data['message'];
document.querySelector('#chat-log').value += (message + '\n');
document.getElementById("chat-log").scrollTop = document.getElementById("chat-log").scrollHeight;
};
// Set User
window.onload = function(){
userName = sessionStorage.getItem("user");
if (userName==null || userName===false) {
userName = prompt("Please enter a username:");
};
return userName;
}
//Join message
function chatJoin() {
if(chatSocket.readyState == false) {
window.setTimeout(chatJoin, 500); /* Wait 500 milliseconds*/
} else {
var message = userName + " has joined the chat."
chatSocket.send(JSON.stringify({
'message': message
}));
}
}
chatJoin();
// chatSocket.onclose = function(e) {
// console.error('Chat socket closed unexpectedly');
// };
// Sign off message
window.unload = function(e) {
var message = userName +"has left the chat."
chatSocket.send(JSON.stringify({
'message': message
}));
};
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 currentDate = new Date();
var currentTime = currentDate.toLocaleTimeString();
var messageInputDom = document.querySelector('#chat-message-input');
var message = userName + " " + currentTime + currentZone + ': ' + messageInputDom.value;
chatSocket.send(JSON.stringify({
'message': message
}));
messageInputDom.value = '';
};
消费者
from channels.generic.websocket import AsyncWebsocketConsumer
from channels.generic.websocket import WebsocketConsumer
import json
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
# 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']
# Send message to WebSocket
await self.send(text_data=json.dumps({
'message': message
}))
我也尝试过这样的断开连接功能,我希望在消息中包含用户名,以便它需要接收一些数据:
async def disconnect(self, text_data, close_code):
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
}
)
# Leave room group
await self.channel_layer.group_discard(
self.room_group_name,
self.channel_name
)
与其从断开连接的客户端发送“用户已断开连接”消息,不如让服务器来执行
因此,在断开连接时,在放弃通话组之前,发送XXX已离开聊天室。消息。这是我考虑的方法。您知道如何将数据传递到断开连接功能吗?似乎断开功能无法接收数据?我将在问题中重新添加我所累的内容的细节,当我注意到disconnect不接受text_数据参数的问题时,我将其删除。您不需要更改disconnect函数的签名,因为它是一个您不调用自己的钩子。每个使用者连接都在作用域中存储了上下文信息。如果您使用的是文档中使用的身份验证方法,那么您可以从self.scop['user']获取用户,然后从该用户获取用户名。您可以将任何其他上下文信息存储在connect中的作用域a中,并使其可供其他方法访问。我没有使用身份验证,因为我试图在没有后端的情况下构建项目。userName变量是一个使用JavaScript设置的变量,存储在会话中。我发现,设置一个类似于self.user_名称的变量在全局范围内起作用,使其可用于断开连接功能。你知道我可以通过websocket发送JavaScript变量的方法吗?我尝试了使用.send()以JSON的形式发送它。在当前receive()函数中,将self.user_name设置为text_data_json['message']的测试未成功。我需要一种获取var的方法,但不需要发送它。我看到了这个问题,因为消费者是后端代码,他们不是孤立于用户的,传递用户var只会保留最近加入的用户。您对实现身份验证的简单方法有何建议?我唯一希望保留的是用户名和适当的会话。有没有办法在不实现数据库的情况下在python代码中缓存这些信息?这里的文档展示了如何使用内置会话身份验证。对于使用者,每个实例都用于单独的连接,因此您可以在使用者对象中存储特定用户的值。这就是自我范围的本质。就像普通的django视图一样,它有request.user。您还可以在启动websocket连接时将用户名作为查询字符串传递。可以在self.scope中访问该值。您可以针对该值发布一个单独的问题,并提供更多详细信息