运维平台的一定少不了这样的场景,即需要实时获取后端数据,例如批量执行的结果,或者监控的状态获取,这个如果单靠浏览器频繁的请求后端接口来更新数据,多少显得有点low
所以对django如何支持websocket长连接进行简单的学习,以便后面集成到项目中
安装channels:
pip3 install channels
先将channels注册到app中:
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'channels', 'app', 'websocket', 'django_celery_beat', 'django_celery_results', ]
在配置文件中指定ASIG路由地址,因为django默认是wsgi协议,channels就是通过asig,异步网关协议实现了websocket
ASGI_APPLICATION = 'captain.routing.application'
然后启动django:
创建一个独立的app:
python manage.py startapp websocket
在项目目录下创建asgi.py文件:
""" ASGI entrypoint. Configures Django and then runs the application defined in the ASGI_APPLICATION setting. """ import os import django from channels.routing import get_default_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'captain.settings') django.setup() application = get_default_application()
在项目目录下创建路由文件:
from channels.auth import AuthMiddlewareStack from channels.routing import ProtocolTypeRouter, URLRouter import websocket.routing application = ProtocolTypeRouter({ 'websocket': AuthMiddlewareStack( URLRouter( websocket.routing.websocket_urlpatterns ) ), })
在app下面创建路由文件,将path和处理webscoket请求的函数进行绑定:
from django.urls import path from websocket.consumers import ChatConsumer websocket_urlpatterns = [ path('ws/chat/', ChatConsumer), ]
在app下面创建视图,处理请求函数:
from channels.generic.websocket import WebsocketConsumer from channels.exceptions import StopConsumer class ChatConsumer(WebsocketConsumer): def websocket_connect(self, message): """ 客户端发送请求进来,触发此方法 :param message: :return: """ self.accept() def websocket_receive(self, message): """ 客户端发送消息,触发此方法,并返回数据 :param message: :return: """ print(message) msg = message['text'] self.send(msg) def websocket_disconnect(self, message): """ 客户端主动断开链接,触发此方法 :param message: :return: """ # 服务端触发异常 StopConsumer raise StopConsumer
创建前端测试文件:
➜ ~ cat socket.html <div> <div> <input type="text" id="txt"> <input type="button" value="send" onclick="sendMsg();"> <input type="button" value="close" onclick="closeConn();"> </div> <h2>聊天记录</h2> <div id="content"> </div> </div> <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.0/jquery.min.js"></script> <script> var ws = new WebSocket("ws://127.0.0.1:8088/ws/chat/"); ws.onopen = function(){ // 客户端验证握手环节完成之后,自动执行该方法 console.log("链接成功。。。") }; ws.onmessage = function (event) { // 接受服务端发送的消息 // 客户端完成握手验证之后 触发该方法 console.log(event.data); var tag = $("<div>"); tag.text(event.data); $("#content").append(tag); console.log(1) }; function sendMsg() { // ws.send():发送消息 ws.send($("#txt").val()); }; function closeConn() { // ws.close():关闭Websocket链接 console.log("断开链接。。。"); ws.close(); }; </script>
一个简单的聊天室就创建好了