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模块,