django 項目配置websocket
1.安裝包
channels==3.0.4 channels-redis==3.3.1
2.修改項目配置文件settings.py
INSTALLED_APPS = [ 'simpleui', 'corsheaders', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app.apps.AppConfig', 'rest_framework', 'django_filters', 'channels', 'channels_redis', ]
ASGI_APPLICATION = "項目名稱.routing.application" # 上面新建的 asgi 應用
WSGI_APPLICATION = '項目名稱.wsgi.application'
CHANNEL_LAYERS = {
'default': {
# 這里用到了 channels_redis
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
'hosts': [(cf.get("redis", "LOCATION"), cf.get("redis", "REDISPORT"))], # 配置你自己的 redis 服務信息
},
}
}
# redis配置
CACHES = {
"default": {
"BACKEND": "django_redis.cache.RedisCache",
"LOCATION": "redis://{}:{}".format(cf.get("redis", "LOCATION"), cf.get("redis", "REDISPORT")),
"OPTIONS": {
"CLIENT_CLASS": "django_redis.client.DefaultClient",
"CONNECTION_POOL_KWARGS": {"max_connections": 100}
# "PASSWORD": "密碼",
}
}
}
3.項目目錄下新建 > routing.py
from channels.auth import AuthMiddlewareStack from channels.routing import ProtocolTypeRouter, URLRouter import app.routing application = ProtocolTypeRouter({ # (http->django views is added by default) # 普通的HTTP請求不需要我們手動在這里添加,框架會自動加載過來 'websocket': AuthMiddlewareStack( URLRouter( app.routing.websocket_urlpatterns ) ), })
項目目錄下新建 > pro_asgi.py (django 通過uwsig 啟動需要用到, 本地開發環境可以不用)
生產環境啟動命令
nohup daphne -b 0.0.0.0 -p 9011 項目名稱.pro_asgi:application
""" ASGI config for SOWebOffice project. It exposes the ASGI callable as a module-level variable named ``application``. For more information on this file, see https://docs.djangoproject.com/en/3.2/howto/deployment/asgi/ """ import os #from django.core.asgi import get_asgi_application import django from channels.routing import get_default_application os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'SOSendMessage.settings') django.setup() application = get_default_application()
4.項目 app 目錄下新建 > consumers.py
import json, uuid import datetime import time from asgiref.sync import async_to_sync import multiprocessing from channels.generic.websocket import WebsocketConsumer from rest_framework_jwt.settings import api_settings from django.contrib.auth.models import Permission, User from django.core.cache import cache # 引入緩存模塊 class ChatConsumer(WebsocketConsumer): def connect(self): print("connect") # 當 websocket 一鏈接上以后觸發該函數 try: dataDict = str(self.scope["query_string"], encoding='utf-8').split("&") token = dataDict[0].replace("token=", "") jwt_decode_handler = api_settings.JWT_DECODE_HANDLER user_dict = jwt_decode_handler(token) print("user_dict===>", user_dict) cuser = User.objects.filter(username=str(user_dict["username"])).first() self.user = cuser self.room_group_name = str(cuser.email).split('@')[0] # 'chat_%s' % str(self.scope["query_string"], encoding='utf-8').split("=")[1] print("room_group_name=======>", self.room_group_name) # 注意 `group_add` 只支持異步調用,所以這里需要使用`async_to_sync`轉換為同步調用 async_to_sync(self.channel_layer.group_add)( self.room_group_name, self.channel_name ) # 接受該鏈接 self.accept() except Exception as ex: print("Exception=============>", ex.args) def disconnect(self, close_code): # 斷開鏈接是觸發該函數 # 將該鏈接移出聊天室 async_to_sync(self.channel_layer.group_discard)( self.room_group_name, self.channel_name ) def receive(self, text_data): # 前端發送來消息時,通過這個接口傳遞 # text_data_json = json.loads(text_data) # message = text_data_json['message'] async_to_sync(self.channel_layer.group_send)( self.room_group_name, { # 這里的type要在當前類中實現一個相應的函數, # 下划線或者'.'的都會被Channels轉換為下划線處理, # 所以這里寫 'chat.message'也沒問題 'type': 'chat_message', 'message': text_data } ) def chat_message(self, event): message = event['message'] # Send message to WebSocket self.send(text_data=json.dumps({ 'message': message }))
5.項目 app 目錄下新建 > routing.py
from django.urls import path from app.consumers import ChatConsumer websocket_urlpatterns = [ # 消息推送socket path('somessws/chat/', ChatConsumer.as_asgi()) ]
6.啟動django 項目如下圖表示成功
7.通過postman測試如下 表示websocket 配置成功
項目目錄
項目依賴
aioredis==1.3.1 asgiref==3.4.1 async-timeout==4.0.2 attrs==21.4.0 autobahn==22.1.1 Automat==20.2.0 certifi==2021.10.8 cffi==1.15.0 channels==3.0.4 channels-redis==3.3.1 charset-normalizer==2.0.9 configparser==5.2.0 constantly==15.1.0 cryptography==36.0.1 daphne==3.0.2 Django==4.0 django-cors-headers==3.10.1 django-filter==21.1 django-redis==5.1.0 django-simpleui==2022.1 djangorestframework==3.12.2 djangorestframework-jwt==1.11.0 hiredis==2.0.0 hyperlink==21.0.0 idna==3.3 incremental==21.3.0 msgpack==1.0.3 pyasn1==0.4.8 pyasn1-modules==0.2.8 pycparser==2.21 PyJWT==1.7.1 PyMySQL==1.0.2 pyOpenSSL==22.0.0 pytz==2021.3 redis==3.5.3 requests==2.26.0 service-identity==21.1.0 six==1.16.0 sqlparse==0.4.2 Twisted==22.1.0 txaio==21.2.1 typing_extensions==4.0.1 urllib3==1.26.7 uWSGI==2.0.18 zope.interface==5.4.0