Django 项目使用websocket
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