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

 

posted @ 2022-02-11 09:41  汪丛兴  阅读(1493)  评论(0编辑  收藏  举报