在Django5中使用Websocket进行通信

Docker安装Redis

bash 复制代码
docker run --restart=always -p 6379:6379 --name redis -d redis:7.0.12  --requirepass zhangdapeng520

安装依赖

参考文档:https://channels.readthedocs.io/en/latest/installation.html

bash 复制代码
pip install "channels[daphne]"

展示聊天页面

新增:chat/templates/chat/index.html

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>Chat Rooms</title>
</head>
<body>
    请输入您要进入的房间名称<br>
    <input id="room-name-input" type="text" size="100"><br>
    <input id="room-name-submit" type="button" value="进入房间">

    <script>
        // 输入框聚焦
        document.querySelector('#room-name-input').focus();
        // 输入框按下enter键,相当于点击提交按钮
        document.querySelector('#room-name-input').onkeyup = function(e) {
            if (e.key === 'Enter') {
                document.querySelector('#room-name-submit').click();
            }
        };
        // 提交按钮点击
        document.querySelector('#room-name-submit').onclick = function(e) {
            // 获取房间名称
            const roomName = document.querySelector('#room-name-input').value;
            // 重定向到指定房间
            window.location.pathname = '/chat/' + roomName + '/';
        };
    </script>
</body>
</html>

修改:chat/views.py

python 复制代码
from django.shortcuts import render


def index(request):
    """首页路由"""
    return render(request, "chat/index.html")

新增:chat/urls.py

python 复制代码
from django.urls import path

from . import views


urlpatterns = [
    path("", views.index, name="index"),
]

修改:Django5Websocket/urls.py

python 复制代码
from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path("chat/", include("chat.urls")),
    path("admin/", admin.site.urls),
]

启动服务,浏览器访问:http://localhost:8000

建立Websocket服务

新增:chat/consumers.py

python 复制代码
import json

from channels.generic.websocket import WebsocketConsumer


class ChatConsumer(WebsocketConsumer):
    """Websocket通信类"""
    def connect(self):
        """建立连接"""
        self.accept()

    def disconnect(self, close_code):
        """断开连接"""
        pass

    def receive(self, text_data):
        """接收消息"""
        # 转换为JSON类型
        text_data_json = json.loads(text_data)
        # 提取消息
        message = text_data_json["message"]
        # 重新发送JSON文本消息
        self.send(text_data=json.dumps({"message": message}))

新增:chat/routing.py

python 复制代码
from django.urls import re_path

from . import consumers

websocket_urlpatterns = [
    # 定义websocket的连接
    re_path(r"ws/chat/(?P<room_name>\w+)/$", consumers.ChatConsumer.as_asgi()),
]

修改:Django5Websocket/wsgi.py

python 复制代码
import os
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator
from django.core.asgi import get_asgi_application
from chat.routing import websocket_urlpatterns

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'Django5Websocket.settings')

django_asgi_app = get_asgi_application()
application = ProtocolTypeRouter({
    "http": django_asgi_app,
    "websoket": AllowedHostsOriginValidator(
        AuthMiddlewareStack(URLRouter(websocket_urlpatterns))
    )
})

修改:chat/views.py

python 复制代码
from django.shortcuts import render


def index(request):
    """首页路由"""
    return render(request, "chat/index.html")


def room(request, room_name):
    """房间路由"""
    return render(request, "chat/room.html", {"room_name": room_name})

新增:chat/templates/chat/room.html

html 复制代码
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>Chat Room</title>
</head>
<body>
{#聊天日志#}
<textarea id="chat-log" cols="100" rows="20"></textarea><br>
{#消息输入框#}
<input id="chat-message-input" type="text" size="100"><br>
{#提交按钮#}
<input id="chat-message-submit" type="button" value="Send">
{#房间名称#}
{{ room_name|json_script:"room-name" }}
<script>
    // 提取房间名称
    const roomName = JSON.parse(document.getElementById('room-name').textContent);
    // 创建websocket连接
    const chatSocket = new WebSocket(
        'ws://'
        + window.location.host
        + '/ws/chat/'
        + roomName
        + '/'
    );

    // 接收消息
    chatSocket.onmessage = function (e) {
        // 解析接收到的消息
        const data = JSON.parse(e.data);
        // 输出到聊天日志记录
        document.querySelector('#chat-log').value += (data.message + '\n');
    };

    // 关闭websocket
    chatSocket.onclose = function (e) {
        console.error('聊天websocket连接已经被关闭');
    };

    // 消息输入框自动聚焦
    document.querySelector('#chat-message-input').focus();
    // 消息输入框的enter事件
    document.querySelector('#chat-message-input').onkeyup = function (e) {
        if (e.key === 'Enter') {
            document.querySelector('#chat-message-submit').click();
        }
    };
    // 提交按钮的点击事件
    document.querySelector('#chat-message-submit').onclick = function (e) {
        // 获取要输入的消息
        const messageInputDom = document.querySelector('#chat-message-input');
        const message = messageInputDom.value;
        // 发送消息
        chatSocket.send(JSON.stringify({
            'message': message
        }));
        // 清空输入框内容
        messageInputDom.value = '';
    };
</script>
</body>
</html>

迁移数据:

bash 复制代码
python manage.py migrate

Docker安装Redis

安装Redis:

bash 复制代码
docker run --restart=always -p 6379:6379 --name redis -d redis:7.0.12  --requirepass zhangdapeng520

安装依赖:

python 复制代码
pip install channels_redis

配置信息:

python 复制代码
ASGI_APPLICATION = 'Django5Websocket.asgi.application'
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": ["redis://:zhangdapeng520@127.0.0.1:6379/0"],
        },
    },
}

启动服务

启动服务,浏览器访问:http://localhost:8000/chat/test/

相关推荐
njnu@liyong2 小时前
图解HTTP-HTTP报文
网络协议·计算机网络·http
kaixin_learn_qt_ing4 小时前
了解RPC
网络·网络协议·rpc
爱吃水果蝙蝠汤6 小时前
DATACOM-IP单播路由(BGP)-复习-实验
网络·网络协议·tcp/ip
言成言成啊13 小时前
TCP与UDP的端口连通性
网络协议·tcp/ip·udp
敲代码娶不了六花13 小时前
对计算机网络中“层”的理解
网络·网络协议·tcp/ip·计算机网络
x66ccff13 小时前
HTTPS如何通过CA证书实现安全通信,以及HTTPS的局限性
网络协议·安全·https
Graceful_scenery13 小时前
https双向认证
服务器·网络·网络协议·http·https
LuiChun13 小时前
Django 模板分割及多语言支持案例【需求文档】-->【实现方案】
数据库·django·sqlite
凡人的AI工具箱13 小时前
每天40分玩转Django:Django管理界面
开发语言·数据库·后端·python·django
中科院提名者13 小时前
Django连接mysql数据库报错ModuleNotFoundError: No module named ‘MySQLdb‘
数据库·mysql·django