django channels使用和配置及實(shí)現(xiàn)群聊
1.1WebSocket原理
http協(xié)議
- 連接
- 數(shù)據(jù)傳輸
- 斷開(kāi)連接
websocket協(xié)議,是建立在http協(xié)議之上的。
- 連接,客戶(hù)端發(fā)起。
- 握手(驗(yàn)證),客戶(hù)端發(fā)送一個(gè)消息,后端接收到消息再做一些特殊處理并返回。 服務(wù)端支持websocket協(xié)議。
1.2django框架
django默認(rèn)不支持websocket,需要安裝組件:
pip install channels
配置:
注冊(cè)channels
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'channels',
]
在settings.py中添加 asgi_application
ASGI_APPLICATION = "ws_demo.asgi.application"
修改asgi.py文件
import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from . import routing
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'ws_demo.settings')
# application = get_asgi_application()
application = ProtocolTypeRouter({
"http": get_asgi_application(),
"websocket": URLRouter(routing.websocket_urlpatterns),
})
在settings.py的同級(jí)目錄創(chuàng)建 routing.py
from django.urls import re_path
from app01 import consumers
websocket_urlpatterns = [
re_path(r'ws/(?P<group>\w+)/$', consumers.ChatConsumer.as_asgi()),
]
在app01目錄下創(chuàng)建 consumers.py,編寫(xiě)處理處理websocket的業(yè)務(wù)邏輯。
from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer
class ChatConsumer(WebsocketConsumer):
def websocket_connect(self, message):
# 有客戶(hù)端來(lái)向后端發(fā)送websocket連接的請(qǐng)求時(shí),自動(dòng)觸發(fā)。
# 服務(wù)端允許和客戶(hù)端創(chuàng)建連接。
self.accept()
def websocket_receive(self, message):
# 瀏覽器基于websocket向后端發(fā)送數(shù)據(jù),自動(dòng)觸發(fā)接收消息。
print(message)
self.send("不要回復(fù)不要回復(fù)")
# self.close()
def websocket_disconnect(self, message):
# 客戶(hù)端與服務(wù)端斷開(kāi)連接時(shí),自動(dòng)觸發(fā)。
print("斷開(kāi)連接")
raise StopConsumer()
小結(jié)
基于django實(shí)現(xiàn)websocket請(qǐng)求,但現(xiàn)在為止只能對(duì)某個(gè)人進(jìn)行處理。
2.0 實(shí)現(xiàn)群聊
2.1 群聊(一)
前端:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.message {
height: 300px;
border: 1px solid #dddddd;
width: 100%;
}
</style>
</head>
<body>
<div class="message" id="message"></div>
<div>
<input type="text" placeholder="請(qǐng)輸入" id="txt">
<input type="button" value="發(fā)送" onclick="sendMessage()">
<input type="button" value="關(guān)閉連接" onclick="closeConn()">
</div>
<script>
socket = new WebSocket("ws://127.0.0.1:8000/room/123/");
// 創(chuàng)建好連接之后自動(dòng)觸發(fā)( 服務(wù)端執(zhí)行self.accept() )
socket.onopen = function (event) {
let tag = document.createElement("div");
tag.innerText = "[連接成功]";
document.getElementById("message").appendChild(tag);
}
// 當(dāng)websocket接收到服務(wù)端發(fā)來(lái)的消息時(shí),自動(dòng)會(huì)觸發(fā)這個(gè)函數(shù)。
socket.onmessage = function (event) {
let tag = document.createElement("div");
tag.innerText = event.data;
document.getElementById("message").appendChild(tag);
}
// 服務(wù)端主動(dòng)斷開(kāi)連接時(shí),這個(gè)方法也被觸發(fā)。
socket.onclose = function (event) {
let tag = document.createElement("div");
tag.innerText = "[斷開(kāi)連接]";
document.getElementById("message").appendChild(tag);
}
function sendMessage() {
let tag = document.getElementById("txt");
socket.send(tag.value);
}
function closeConn() {
socket.close(); // 向服務(wù)端發(fā)送斷開(kāi)連接的請(qǐng)求
}
</script>
</body>
</html>后端:
from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer
CONN_LIST = []
class ChatConsumer(WebsocketConsumer):
def websocket_connect(self, message):
print("有人來(lái)連接了...")
# 有客戶(hù)端來(lái)向后端發(fā)送websocket連接的請(qǐng)求時(shí),自動(dòng)觸發(fā)。
# 服務(wù)端允許和客戶(hù)端創(chuàng)建連接(握手)。
self.accept()
CONN_LIST.append(self)
def websocket_receive(self, message):
# 瀏覽器基于websocket向后端發(fā)送數(shù)據(jù),自動(dòng)觸發(fā)接收消息。
text = message['text'] # {'type': 'websocket.receive', 'text': '阿斯蒂芬'}
print("接收到消息-->", text)
res = "{}SB".format(text)
for conn in CONN_LIST:
conn.send(res)
def websocket_disconnect(self, message):
CONN_LIST.remove(self)
raise StopConsumer()
2.2 群聊(二)
第二種實(shí)現(xiàn)方式是基于channels中提供channel layers來(lái)實(shí)現(xiàn)。(如果覺(jué)得復(fù)雜可以采用第一種)
setting中配置 。
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels.layers.InMemoryChannelLayer",
}
}
如果是使用的redis 環(huán)境
pip3 install channels-redis
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [('10.211.55.25', 6379)]
},
},
}
consumers中特殊的代碼。
from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer
from asgiref.sync import async_to_sync
class ChatConsumer(WebsocketConsumer):
def websocket_connect(self, message):
# 接收這個(gè)客戶(hù)端的連接
self.accept()
# 將這個(gè)客戶(hù)端的連接對(duì)象加入到某個(gè)地方(內(nèi)存 or redis)1314 是群號(hào)這里寫(xiě)死了
async_to_sync(self.channel_layer.group_add)('1314', self.channel_name)
def websocket_receive(self, message):
# 通知組內(nèi)的所有客戶(hù)端,執(zhí)行 xx_oo 方法,在此方法中自己可以去定義任意的功能。
async_to_sync(self.channel_layer.group_send)('1314', {"type": "xx.oo", 'message': message})
#這個(gè)方法對(duì)應(yīng)上面的type,意為向1314組中的所有對(duì)象發(fā)送信息
def xx_oo(self, event):
text = event['message']['text']
self.send(text)
def websocket_disconnect(self, message):
#斷開(kāi)鏈接要將這個(gè)對(duì)象從 channel_layer 中移除
async_to_sync(self.channel_layer.group_discard)('1314', self.channel_name)
raise StopConsumer()
好了分享就結(jié)束了,其實(shí)總的來(lái)講介紹的還是比較淺
如果想要深入一點(diǎn) 推薦兩篇博客
【翻譯】Django Channels 官方文檔 -- Tutorial - 守護(hù)窗明守護(hù)愛(ài) - 博客園
到此這篇關(guān)于django channels使用和配置及實(shí)現(xiàn)群聊的文章就介紹到這了,更多相關(guān)django channels配置內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
使用python和Django完成博客數(shù)據(jù)庫(kù)的遷移方法
下面小編就為大家分享一篇使用python和Django完成博客數(shù)據(jù)庫(kù)的遷移方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-01-01
pandas庫(kù)中to_datetime()方法的使用解析
這篇文章主要介紹了pandas庫(kù)中to_datetime()方法的使用解析,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07
Python利用pdfplumber提取PDF文檔中的表格數(shù)據(jù)并導(dǎo)出
pdfplumber是一個(gè)功能強(qiáng)大的Python庫(kù),可以用于解析PDF文檔并提取其中的文本、表格和圖像等內(nèi)容,下面我們就來(lái)學(xué)習(xí)一下如何使用pdfplumber提取PDF表格數(shù)據(jù)吧2023-12-12
python Django批量導(dǎo)入不重復(fù)數(shù)據(jù)
這篇文章主要介紹了python Django批量導(dǎo)入不重復(fù)數(shù)據(jù)的相關(guān)資料,需要的朋友可以參考下2016-03-03
python定時(shí)器(Timer)用法簡(jiǎn)單實(shí)例
這篇文章主要介紹了python定時(shí)器(Timer)用法,以一個(gè)簡(jiǎn)單實(shí)例形式分析了定時(shí)器(Timer)實(shí)現(xiàn)延遲調(diào)用的技巧,需要的朋友可以參考下2015-06-06
Python3爬蟲(chóng)里關(guān)于代理的設(shè)置總結(jié)
在本篇文章里小編給大家整理的是一篇關(guān)于Python3爬蟲(chóng)里關(guān)于代理的設(shè)置總結(jié),需要的朋友們可以參考下。2020-07-07
Python使用socket_TCP實(shí)現(xiàn)小文件下載功能
這篇文章主要介紹了Python使用socket_TCP實(shí)現(xiàn)小文件下載功能,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10

