詳解Django-channels 實(shí)現(xiàn)WebSocket實(shí)例
引入
先安裝三個(gè)模塊
pip install channels pip install channels_redis pip install pywin32
創(chuàng)建一個(gè)Django項(xiàng)目和一個(gè)app
項(xiàng)目名隨意,app名隨意。這里項(xiàng)目名為 django_websocket_demo ,app名 chat
把a(bǔ)pp文件夾下除了 views.py 和 __init__.py 的文件都刪了,最終項(xiàng)目目錄結(jié)構(gòu)如下:
django_websocket_demo/ manage.py django_websocket_demo/ __init__.py settings.py urls.py wsgi.py chat/ __init__.py views.py
在app下新建一個(gè)templates文件夾用來存放HTML頁面:
chat/ __init__.py templates/ chat/ index.html views.py
index.html 內(nèi)容如下:
<!-- chat/templates/chat/index.html --> <!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>Chat Rooms</title> </head> <body> What chat room would you like to enter?<br/> <input id="room-name-input" type="text" size="100"/><br/> <input id="room-name-submit" type="button" value="Enter"/> <script> document.querySelector('#room-name-input').focus(); document.querySelector('#room-name-input').onkeyup = function(e) { if (e.keyCode === 13) { // enter, return document.querySelector('#room-name-submit').click(); } }; document.querySelector('#room-name-submit').onclick = function(e) { var roomName = document.querySelector('#room-name-input').value; window.location.pathname = '/chat/' + roomName + '/'; }; </script> </body> </html>
在 chat/views.py 中添加視圖函數(shù):
from django.shortcuts import render def index(request): return render(request, 'chat/index.html', {})
添加 chat/urls.py 文件并設(shè)置路由信息:
from django.urls import re_path from . import views urlpatterns = [ re_path(r'^$', views.index, name='index'), ]
在項(xiàng)目路由 django_websocket_demo/urls.py 中配置路由信息:
from django.conf.urls import include, url from django.contrib import admin urlpatterns = [ url(r'^chat/', include('chat.urls')), url(r'^admin/', admin.site.urls), ]
在 settings.py 文件同級(jí)目錄下新建 routing.py 文件,內(nèi)容如下:
from channels.routing import ProtocolTypeRouter application = ProtocolTypeRouter({ # (http->django views is added by default) })
把 channels 注冊(cè)在 settings.py 里:
INSTALLED_APPS = [ 'channels', 'chat', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ]
在 settings.py 文件中,添加如下配置項(xiàng):
# django_websocket_demo/settings.py # Channels # Channels ASGI_APPLICATION = 'django_websocket_demo.routing.application'
創(chuàng)建聊天頁面
創(chuàng)建一個(gè) chat/templates/chat/room.html 文件,添加如下內(nèi)容:
<!-- chat/templates/chat/room.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"/> </body> <script> var roomName = {{ room_name_json }}; var chatSocket = new WebSocket( 'ws://' + window.location.host + '/ws/chat/' + roomName + '/'); chatSocket.onmessage = function(e) { var data = JSON.parse(e.data); var message = data['message']; document.querySelector('#chat-log').value += (message + '\n'); }; chatSocket.onclose = function(e) { console.error('Chat socket closed unexpectedly'); }; document.querySelector('#chat-message-input').focus(); document.querySelector('#chat-message-input').onkeyup = function(e) { if (e.keyCode === 13) { // enter, return document.querySelector('#chat-message-submit').click(); } }; document.querySelector('#chat-message-submit').onclick = function(e) { var messageInputDom = document.querySelector('#chat-message-input'); var message = messageInputDom.value; chatSocket.send(JSON.stringify({ 'message': message })); messageInputDom.value = ''; }; </script> </html>
在 chat/views.py 中添加一個(gè)處理 room的視圖函數(shù):
from django.shortcuts import render from django.utils.safestring import mark_safe import json def index(request): return render(request, 'chat/index.html', {}) def room(request, room_name): return render(request, 'chat/room.html', { 'room_name_json': mark_safe(json.dumps(room_name)) })
在 chat/urls.py 中注冊(cè)路由
from django.urls import re_path from . import views urlpatterns = [ re_path(r'^$', views.index, name='index'), re_path(r'^(?P<room_name>[^/]+)/$', views.room, name='room'), ]
新建 chat/consumers.py 文件,添加如下內(nèi)容:
from channels.generic.websocket import AsyncWebsocketConsumer import json class ChatConsumer(AsyncWebsocketConsumer): async def connect(self): self.room_name = self.scope['url_route']['kwargs']['room_name'] self.room_group_name = 'chat_%s' % self.room_name # Join room group await self.channel_layer.group_add( self.room_group_name, self.channel_name ) await self.accept() async def disconnect(self, close_code): # Leave room group await self.channel_layer.group_discard( self.room_group_name, self.channel_name ) # Receive message from WebSocket async def receive(self, text_data): text_data_json = json.loads(text_data) message = text_data_json['message'] # Send message to room group await self.channel_layer.group_send( self.room_group_name, { 'type': 'chat_message', 'message': message } ) # Receive message from room group async def chat_message(self, event): message = event['message'] # Send message to WebSocket await self.send(text_data=json.dumps({ 'message': message }))
新建一個(gè) chat/routing.py 文件,添加以下內(nèi)容:
from django.urls import re_path from . import consumers websocket_urlpatterns = [ re_path(r'^ws/chat/(?P<room_name>[^/]+)/$', consumers.ChatConsumer), ]
將 django_websocket_demo/routing.py 文件中修改為以下內(nèi)容:
from channels.auth import AuthMiddlewareStack from channels.routing import ProtocolTypeRouter, URLRouter import chat.routing application = ProtocolTypeRouter({ # (http->django views is added by default) 'websocket': AuthMiddlewareStack( URLRouter( chat.routing.websocket_urlpatterns ) ), })
配置redis
在本地6379端口啟動(dòng)redis : redis-server
在 settings.py 中添加如下配置:
CHANNEL_LAYERS = { 'default': { 'BACKEND': 'channels_redis.core.RedisChannelLayer', 'CONFIG': { "hosts": [('127.0.0.1', 6379)], }, }, }
最后啟動(dòng)Django項(xiàng)目
使用多個(gè)瀏覽器打開http://127.0.0.1:8000/chat/lobby/ ,開始實(shí)時(shí)聊天吧。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- Django實(shí)現(xiàn)WebSocket在線聊天室功能(channels庫)
- Django中如何使用Channels功能
- Django使用channels + websocket打造在線聊天室
- django使用channels實(shí)現(xiàn)通信的示例
- 淺談django channels 路由誤導(dǎo)
- Django使用Channels實(shí)現(xiàn)WebSocket的方法
- Django Channels 實(shí)現(xiàn)點(diǎn)對(duì)點(diǎn)實(shí)時(shí)聊天和消息推送功能
- django使用channels2.x實(shí)現(xiàn)實(shí)時(shí)通訊
- django channels使用和配置及實(shí)現(xiàn)群聊
相關(guān)文章
詳解APScheduler如何設(shè)置任務(wù)不并發(fā)
本文主要介紹了APScheduler如何設(shè)置任務(wù)不并發(fā),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-07-07Python個(gè)人博客程序開發(fā)實(shí)例用戶驗(yàn)證功能
這篇文章主要介紹了怎樣用Python來實(shí)現(xiàn)一個(gè)完整的個(gè)人博客系統(tǒng),我們通過實(shí)操上手的方式可以高效的鞏固所學(xué)的基礎(chǔ)知識(shí),感興趣的朋友一起來看看吧2022-12-12Python參數(shù)傳遞實(shí)現(xiàn)過程及原理詳解
這篇文章主要介紹了Python參數(shù)傳遞實(shí)現(xiàn)過程及原理詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05Python時(shí)間轉(zhuǎn)化方法超全總結(jié)
在生活和工作中,我們每個(gè)人每天都在和時(shí)間打交道。本文就為大家總結(jié)了Python實(shí)現(xiàn)時(shí)間轉(zhuǎn)化的多種方法,快來跟隨小編一起學(xué)習(xí)一下吧2022-03-03pandas 如何保存數(shù)據(jù)到excel,csv
這篇文章主要介紹了pandas 如何保存數(shù)據(jù)到excel,csv的實(shí)現(xiàn)方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07python 實(shí)現(xiàn)在txt指定行追加文本的方法
下面小編就為大家分享一篇python 實(shí)現(xiàn)在txt指定行追加文本的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2018-04-04使用Python的SymPy庫解決數(shù)學(xué)運(yùn)算問題的方法
這篇文章主要介紹了使用Python的SymPy庫解決數(shù)學(xué)運(yùn)算問題的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-03-03利用Python實(shí)現(xiàn)自定義連點(diǎn)器
這篇文章主要介紹了如何利用Python實(shí)現(xiàn)自定義連點(diǎn)器,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08Django框架中間件(Middleware)用法實(shí)例分析
這篇文章主要介紹了Django框架中間件(Middleware)用法,結(jié)合實(shí)例形式分析了Django框架中間件(Middleware)的功能、用法及相關(guān)操作技巧,需要的朋友可以參考下2019-05-05