django中如何實現websocket
安裝
pip3 install channles==2.3
1 解釋器版本建議使用python3.6
2 channles模塊版本建議使用2.3
基本配置
配置文件中注冊app
配置文件中定義配置
對應應用下新建py文件並且在文件內部定義變量
完成上述配置以后,django就會既支持http又支持websocket
django,pycharm創建的django項目會自動幫你創建全局的templates文件夾,
也可以在每一個應用下創建templates模板文件夾
如果出現多個應用和全局都有模板文件夾的情況,會優先查找全局,如果全局沒有,會按照配置文件中注冊的app的順序從上往下依次進行查找每一個應用下的templates
每一個應用都可以有自己的urls.py,views.py和templates,static
配置完成以后同時支持http與websocket的原因(源碼解析)
class ProtocolTypeRouter:
"""
Takes a mapping of protocol type names to other Application instances,
and dispatches to the right one based on protocol name (or raises an error)
"""
def __init__(self, application_mapping):
self.application_mapping = application_mapping
if "http" not in self.application_mapping:
self.application_mapping["http"] = AsgiHandler
配置完成以后
routing.py
from channels.routing import ProtocolTypeRouter,URLRouter
from django.conf.urls import url
from app01 import consumers
application = ProtocolTypeRouter({
'websocket':URLRouter([
# websocket相關的路由
url(r'^chat/',consumers.ChatConsumer)
])
})
consumers.py
from channels.generic.websocket import WebsocketConsumer
class ChatConsumer(WebsocketConsumer):
def websocket_connect(self, message):
"""客戶端請求建立鏈接時 自動觸發"""
pass
def websocket_receive(self, message):
"""客戶端發送數據過來 自動觸發"""
pass
def websocket_disconnect(self, message):
"""客戶端斷開鏈接之后 自動觸發"""
pass
"""
http協議
index路徑 index視圖函數
訪問:瀏覽器窗口直接輸入的地址的
websocket協議
chat路徑 ChatConsumer視圖類
訪問:new WebSocket對象訪問
"""
真正通過websocket實現群聊功能:
通過自己維護一個列表存儲鏈接對象的方式完成了簡易版本的群聊,其實還可以用channels提供的模塊,channel-layers
# 后端 三個方法
from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer
consumer_object_list = []
class ChatConsumer(WebsocketConsumer):
def websocket_connect(self, message):
# 客戶端請求鏈接時 自動觸發
print('請求鏈接')
self.accept()
# 建立鏈接 並且自動幫你維護每一個客戶端
# 將鏈接在列表中存儲一份
consumer_object_list.append(self)
def websocket_receive(self, message):
# 客戶端發送數據過來 自動觸發
print(message)
text = message.get('text')
# # 給客戶端發送消息 單獨發送
# self.send(text_data=text)
# 給所有的鏈接對象發送數據
for obj in consumer_object_list:
obj.send(text_data=text)
def websocket_disconnect(self, message):
# 客戶端斷開鏈接之后 自動觸發
print('斷開鏈接')
# 客戶端斷開之后,應該將當前對象移除
consumer_object_list.remove(self)
raise StopConsumer()
# 前端四個方法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
<link href="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcss.com/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
<h1>聊天室</h1>
<input type="text" id="txt">
<button onclick="sendMsg()">發送</button>
<h1>聊天記錄</h1>
<div class="record"></div>
<script>
var ws = new WebSocket('ws://127.0.0.1:8000/chat/');
// 1 握手環節驗證成功后自動觸發 onopen
ws.onopen = function () {
console.log('握手成功!')
};
// 2 給服務端發送消息 人為觸發 send
function sendMsg() {
ws.send($('#txt').val())
}
// 3 服務端一旦有了消息 自動觸發 onmessage
ws.onmessage = function (args) {
// 獲取發送的數據
// 創建p標簽
var pEle = $('<p>');
pEle.text(args.data);
$('.record').append(pEle)
};
// 4 斷開鏈接之后 自動觸發 onclose
ws.onclose = function () {
ws.close()
}
</script>
</body>
</html>