本笔记主要参考《Django应用开发实战》《Django企业开发实战》,这两本书前者详细,后者精炼。学习之后真的是感觉自己进步了很多。值得一读,如果您遇到了值得一读的书籍,欢迎推荐给我,大家共同进步。
Web聊天室的实现方法有多种,下面将简要介绍一下实现方法
django实现websocket大致上有两种方式,一种channels,一种是dwebsocket。channels依赖于redis,twisted等
提示:以下是本篇文章正文内容,下面案例可供参考
pip install channels
pip channels_redis
pip install pypiwin32
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'channels', # 添加channels功能
'chat',
]
ASGI_APPLICATION = '项目名.routing.application'
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [('127.0.0.1', 6379)],
},
},
}
说明:
from channels.routing import ProtocolTypeRouter
from channels.routing import URLRouter
from .urls import websocket_urlpatterns
application = ProtocolTypeRouter({
# (http->django views is added by default)
'websocket': AuthMiddlewareStack(
URLRouter(
websocket_urlpatterns
)
),
})
说明:
定义这个文件是为了响应ASGI_APPLICATION定义application对象,将Django与该插件建立连接。
from django.urls import path, include
from .consumers import ChatConsumer
urlpatterns = [
path('', include(('chat.urls', 'chat'), namespace='chat'))
]
websocket_urlpatterns = [
path('ws/chat//' , ChatConsumer),
]
说明:
# from asgiref.sync import async_to_sync
# from channels.generic.websocket import WebsocketConsumer
# import json
#
# # 将消费者代码为同步。
# class ChatConsumer(WebsocketConsumer):
# 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
# async_to_sync(self.channel_layer.group_add)(
# self.room_group_name,
# self.channel_name
# )
#
# self.accept()
#
# def disconnect(self, close_code):
# # Leave room group
# async_to_sync(self.channel_layer.group_discard)(
# self.room_group_name,
# self.channel_name
# )
#
# # Receive message from WebSocket
# def receive(self, text_data):
# text_data_json = json.loads(text_data)
# message = text_data_json['message']
#
# # Send message to room group
# async_to_sync(self.channel_layer.group_send)(
# self.room_group_name,
# {
# 'type': 'chat_message',
# 'message': message
# }
# )
#
# # Receive message from room group
# def chat_message(self, event):
# message = event['message']
#
# # Send message to WebSocket
# self.send(text_data=json.dumps({
# 'message': message
# }))
#-------------low------------
# 将消费者代码重写为异步,以提高其性能。
from channels.generic.websocket import AsyncWebsocketConsumer
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
}))
大致思路:在应用urls中设置两个路由:创建聊天和进入聊天室。在创建聊天室后即跳转到进入聊天室路由。进入聊天室路由网页设置:使网页与项目插件连接,设置接收和发送信息(也可以设置异常事件触发器)。下面步骤
chat urls
from django.urls import path
from .views import *
urlpatterns = [
# 用于开启新的聊天室
path('', newChat, name='newChat'),
# 创建聊天室
path('/' , room, name='room'),
]
chat views
from django.shortcuts import render
# 用于创建或进入聊天室
def newChat(request):
return render(request, 'chat.html', locals())
# 创建聊天室
def room(request, room_name):
return render(request, 'room.html', locals())
chat.html(截取部分重要)
<body>
<div>请输入聊天室名称</div>
<br/>
<input id="input" type="text" size="30"/>
<br/>
<input id="submit" type="button" value="进 入"/>
<script>
document.querySelector('#input').focus();
document.querySelector('#input').onkeyup = function(e) {
if (e.keyCode === 13) { // enter, return
document.querySelector('#submit').click();
}
};
document.querySelector('#submit').onclick = function(e) {
var roomName = document.querySelector('#input').value;
window.location.pathname = '/' + roomName + '/';
};
</script>
</body>
说明:
确定聊天室名称后,单击进入或者回车将触发javaScript脚本。
room.html
<body>
<textarea id="chat-log" cols="50" rows="6"></textarea>
<br/>
<input id="input" type="text" size="50"/><br/>
<input id="submit" type="button" value="发 送"/>
</body>
<script>
var roomName = '{{ room_name }}';
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'];
document.querySelector('#chat-log').value += (message + '\n');
};
chatSocket.onclose = function(e) {
console.error('Chat socket closed unexpectedly');
};
document.querySelector('#input').focus();
document.querySelector('#input').onkeyup = function(e) {
if (e.keyCode === 13) { // enter, return
document.querySelector('#submit').click();
}
};
document.querySelector('#submit').onclick = function(e) {
var messageInputDom = document.querySelector('#input');
var message = messageInputDom.value;
chatSocket.send(JSON.stringify({
'message': message
}));
messageInputDom.value = '';
};
</script>
说明:
var chatSocket部分为了网页与项目插件连接
chatSocket.onmessage接收数据,并展示到文本框
chatSocket.onclose关闭连接,当出现异常时触发
document.querySelector发送数据
querySelector将文本展示到网页textarea组件中。