Django中使用websocket並實現簡易聊天室


django使用websocket並實現簡易聊天室

django默認只支持http協議

如果你想讓django即支持http協議又支持websocket協議,則需要做以下配置

前期配置

前提需要安裝channels:

channles的安裝:

"""
注意事項
	1.不要安裝最新版本的channles,建議安裝2.3版本即可
	2.python解釋器建議使用3.6
"""
pip3 install channels==2.3

1.配置文件中注冊channels應用

INSTALLED_APPS = [
    # 1 注冊channles應用
    'channels'
]

2.settings.py配置文件配置參數

# 2 配置啟動需要的參數
ASGI_APPLICATION = 'myapi.routing.application'
# ASGI_APPLICATION = '項目名同名的文件夾名.內部的py文件名(默認就叫routing).routing文件內的變量名(默認就叫application)'

3.固定配置

# 在項目名同名的文件夾下創建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)
    ])
})

總結:配置完成后django由原來默認的wsgiref替換成asgi啟動(asgi內部是基於達芙妮)

上述配置完成后 ,django就會同時支持http協議和websocket協議

"""
原先基於http協議的路由與視圖函數對應關系還是跟之前一樣urls.py、views.py

針對websocket協議的路由與視圖函數對應關系則需要在routing.py和consumers.py(在對應的應用下創建即可)
"""

業務邏輯代碼

# consumers.py
from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer



class ChatConsumer(WebsocketConsumer):
    def websocket_connect(self, message):
        """
        客戶端請求鏈接之后自動觸發
        :param message: 消息數據
        """
        pass
    
    def websocket_receive(self, message):
        """
        客戶端瀏覽器發送消息來的時候自動觸發
        :param message: 消息數據
        """
        pass
    
    def websocket_disconnect(self, message):
        """
        客戶端斷開鏈接之后自動觸發
        :param message:  
        """
        pass

基於channels完成聊天室

"""
http協議
	index	>>> index函數
	訪問:瀏覽器發送請求即可

websocket協議
	chat >>> ChatConsumer類(3個方法)
	訪問:借助於new WebSocket對象
"""
from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer


consumer_object_list = []


class ChatConsumer(WebsocketConsumer):
    def websocket_connect(self, message):
        """
        客戶端請求鏈接之后自動觸發
        :param message: 消息數據
        """
        # print('請求鏈接')
        self.accept()  # 建立鏈接

        # 鏈接成功之后就將當前鏈接對象往列表中存一份
        consumer_object_list.append(self)


    def websocket_receive(self, message):
        """
        客戶端瀏覽器發送消息來的時候自動觸發
        :param message: 消息數據  {'type': 'websocket.receive', 'text': '你好啊 美女'}
        """
        # 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):
        """
        客戶端斷開鏈接之后自動觸發
        :param message:
        """
        # 客戶端斷開鏈接之后 應該將當前客戶端對象從列表中移除
        consumer_object_list.remove(self)
        raise StopConsumer()  # 主動報異常 無需做處理 內部自動捕獲
<h1>聊天室</h1>
<div>
    <input type="text" id="text" placeholder="請輸入">
    <input type="button" value="發送" onclick="sendMsg()">
    <input type="button" value="斷開鏈接" onclick="close()">
</div>

<h1>聊天紀錄</h1>
<div id="content">

</div>

<script>
    var ws = new WebSocket('ws://127.0.0.1:8000/chat/');
    // 1 發送消息 ws.send()
    // 2 握手成功之后 自動觸發  ws.onopen
    // 3 服務端發送消息過來 自動觸發  ws.onmessage
    // 4 斷開鏈接 ws.close()

    // 0 握手成功之后自動觸發
    ws.onopen = function () {
        alert('建立成功')
    };

    // 1 給服務端發送消息
    function sendMsg() {
        ws.send($('#text').val());
    }

    // 2 接受服務端發送過來的消息
    ws.onmessage = function (event) {  // event是對象
        var dataValue = event.data;  // 獲取服務端的數據
        // 用DOM操作將數據動態渲染到頁面上
        var pEle = $('<p>');
        pEle.text(dataValue);
        $('#content').append(pEle)
    };

    // 3 斷開鏈接
    function close() {
        ws.close()
    }
</script>

總結

"""
后端三個方法
	websocket_connect
	websocket_receive
	websocket_disconnect

前端四個方法
	// 1 發送消息 ws.send()
  // 2 握手成功之后 自動觸發  ws.onopen
  // 3 服務端發送消息過來 自動觸發  ws.onmessage
  // 4 斷開鏈接 ws.close()
"""

注意我們上面的代碼實現的群聊功能並不是真正的合理,后續如果想要真正實現群聊功能,官方提供了一個方法channel-layers模塊,


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM