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

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

django默認只支持http協議html

若是你想讓django即支持http協議又支持websocket協議,則須要作如下配置前端

前期配置

前提須要安裝channels:python

channles的安裝:web

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

1.配置文件中註冊channels應用django

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

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

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

3.固定配置api

# 在項目名同名的文件夾下建立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協議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>

總結app

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

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

注意咱們上面的代碼實現的羣聊功能並非真正的合理,後續若是想要真正實現羣聊功能,官方提供了一個方法channel-layers模塊,

相關文章
相關標籤/搜索