使用django+websocket+redis+channels實現簡易聊天室 1.創建一個django項目 從存儲項目的文件夾進入cmd命令行終端,輸入以下命令創建chatroom項目 django-admin startproject chatroom 然後再進入項目文件夾,打開cmd命令行終 ...
使用django+websocket+redis+channels實現簡易聊天室
1.創建一個django項目
從存儲項目的文件夾進入cmd命令行終端,輸入以下命令創建chatroom項目
django-admin startproject chatroom
然後再進入項目文件夾,打開cmd命令行終端,輸入以下命令創建chat應用
python manage.py startapp chat
2.安裝所需模塊
channels的功能必須依賴於redis資料庫,除了安裝channels之外,還需安裝channels_redis模塊,我們使用pip指令分別安裝channels和channels_redis,指令如下:
pip install channels
pip install channels_redis
#channels的功能依賴模塊
pip install pypiwin32
3.在django中配置channels
(1)在項目應用chat里新建urls.py文件
(2)在chatroom文件夾里創建文件consumers.py和routing.py,文件名可以自行命名
(3)在項目應用chat里新建templates文件夾,在templates文件夾里創建模板文件chat.html和room.html,項目結構如下:
(4)執行整個項目的數據遷移,因為channels需要使用django內置的會話session機制,用於區分和識別每個用戶的身份信息
(5)在django的settings.py里將第三方功能應用channels和chat添加到chatroom,配置如下:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'channels',
'chat'
]
(6)由於channels的功能依賴與redis資料庫,因此還需在settings.py里設置channels的功能設置,配置信息如下:
ASGI_APPLICATION = 'chatroom.routing.application'
CHANNEL_LAYERS={
'default':{
'BACKEND':'channels_redis.core.RedisChannelLayer',
'CONFIG':{
"hosts":[('127.0.0.1',6379)],
},
},
}
(7)功能配置CHANNEL_LAYERS用於設置redis資料庫的連接方式,ASGI_APPLICATION指向chatroom的routing.py定義的application對象,該對象把django與channels建立連接,打開chatrooom的routing.py添加如下內容:
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter
from channels.routing import URLRouter
from .urls import websocket_urlpatterns
application = ProtocolTypeRouter({
'websocket':AuthMiddlewareStack(
URLRouter(
websocket_urlpatterns
)
),
})
(8)在chatroom的urls.py中定義路由對象urlpatterns和websocket_urlpatterns,代碼如下:
from django.urls import path,include
from .consumers import ChatConsumer
urlpatterns = [
path("",include(("chat.urls","chat"),namespace="chat"))
]
websocket_urlpatterns=[
#使用同步方式實現
#path('ws/chat/<room_name>/',ChatConsumer),
#如果使用非同步方式實現,路由的視圖必須調用as_asgi()
path('ws/chat/<room_name>/',ChatConsumer.as_asgi()),
]
(9)在chatroom的consumers.py中定義視圖類ChatConsumer,代碼如下:
from channels.generic.websocket import AsyncWebsocketConsumer
import json
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
print("一個客戶端連接了伺服器")
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, code):
# leave room group
await self.channel_layer.group_discard(
self.room_group_name,
self.channel_name
)
print("一個客戶端斷開了連接")
# receive message from websocket
async def receive(self, text_data=None, bytes_data=None):
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
}))
4.web線上聊天功能
(1)在項目應用chat的urls.py中分別定義路由newChat和room,代碼如下:
from django.urls import path
from .views import *
urlpatterns = [
#用於開啟新的聊天室
path('',newChat,name="newChat"),
#創建聊天室
path('<room_name>/',room,name="room")
]
(2)在chat的views.py中定義視圖,代碼如下:
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())
(3)編寫chat.html模板文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<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){
document.querySelector('#submit').click();
}
};
document.querySelector('#submit').onclick=function (e){
var roomName=document.querySelector('#input').value;
window.location.pathname='/'+roomName + '/';
}
</script>
</body>
</html>
(4)編寫room.html模板文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>聊天室{{ room_name }}</title>
</head>
<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="發送"/>
<script>
var roomName='{{ room_name }}';
var chatSocket=new WebSocket(
'ws://' + window.location.host+'/ws/chat/' + roomName +'/'
);
{#將chat發送的數據顯示在多行文本輸入框中#}
chatSocket.onmessage=function (e){
var data=JSON.parse(e.data);
var message=data['message'];
document.querySelector('#chat_log').value+=(message +'\n');
};
{#關閉網頁與chat的Channels連接#}
chatSocket.onclose=function (e){
console.error('Chat socket closed unexpectedly');
};
document.querySelector('#input').focus();
document.querySelector('#input').onkeyup=function (e){
if (e.keyCode===13){
document.querySelector('#submit').click();
}
};
{#網頁向chat的channels發送數據#}
document.querySelector('#submit').onclick=function (e){
var messageInputDom = document.querySelector('#input');
var message=messageInputDom.value;
chatSocket.send(JSON.stringify({
'message':message
}));
messageInputDom.value='';
}
</script>
</body>
</html>
5.測試聊天室功能
運行項目,打開谷歌瀏覽器並訪問127.0.0.1:8000,在文本輸入框輸入聊天室名稱,並單擊進入,如下圖所示:
當成功創建聊天室room0001後,打開另一個瀏覽器訪問127.0.0.1:8000/room0001,聊天室已有兩位用戶線上,然後使用谷歌瀏覽器發送消息,發現在另一瀏覽器可以實時看到消息內容,如下圖所示: