Django+channels+VUE实现即时通讯

VUE比较简单

<template>
  <div style="height:90%">
    <el-container style="height:100%">
      <!-- <el-header>Header</el-header> -->
      <el-main style="height:90%">
        <div v-for="(item,index) in list" :key="index">
          <div v-if="item.user==user" style="width:100%;text-align:right;">
            <el-tag>{{item.value}}</el-tag>
            <el-avatar size="small" :src="circleUrl"></el-avatar>
          </div>
          <div v-else style="width:100%;">
            <el-avatar size="small" :src="circleUrl"></el-avatar>
            <el-tag>{{item.value}}</el-tag>
          </div>
        </div>
      </el-main>
      <el-footer>
        <el-row>
          <el-col :span="22">
            <el-input type="textarea" :rows="1" placeholder="请输入内容" v-model="textarea">
            </el-input>
          </el-col>
          <el-col :span="2">
            <el-button @click="mysend(textarea)">发送</el-button>
          </el-col>
        </el-row>
      </el-footer>
    </el-container>

  </div>
</template>

<script>

export default {
  name: "staff_service",
  data() {
    return {
      room: "",
      user: "",
      list: [],
      textarea: "",
      webSocket: null,
      circleUrl: "https://cube.elemecdn.com/3/7c/3ea6beec64369c2642b92c6726f1epng.png",
    };
  },
  methods: {
    mysend() {
      //发送链接请求
      let _this=this
      if (_this.textarea == "") {
        return
      }
      console.log(_this.webSocket.readyState);
      _this.webSocket.send(_this.textarea);
      _this.textarea = ""
    }
  },
  mounted() {
    var _this = this
    _this.room = JSON.parse(this.$route.query.room);
    _this.user = JSON.parse(this.$route.query.user);
    //判断浏览器是否支持websocket
    if ("WebSocket" in window) {
      console.log("支持");
      _this.webSocket = new WebSocket("ws://127.0.0.1:8000/myapi/ws/chat/" + _this.room + "/" + _this.user + "/");
      _this.webSocket.onopen = function (event) {
        console.log("event",event);
        _this.webSocket.send('text');
      };
      _this.webSocket.onmessage = function (msg) {
        console.log(msg.data);
        console.log(JSON.parse(msg.data).message);
        _this.list.push(JSON.parse(msg.data).message)
      };
      _this.webSocket.onClose = function (msg) {
        console.log("链接已经关闭",msg);
      };
      _this.webSocket.onError = function (err) {
        console.log(err);
      }
    }
  }
}
</script>

<style scoped>
</style>

Django安装channels和redis模块

pip install channels channels-redis

settings.py

ASGI_APPLICATION = '项目名称.asgi.application'

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            # "hosts": [('IP', 端口号)],
            "hosts": ["redis://:密码@IP:端口号/0"],
            "symmetric_encryption_keys": [SECRET_KEY]
        },
    },
}
CACHES = {
    "default": {
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://IP:端口号",  # 安装redis的主机的 IP 和 端口
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
            "CONNECTION_POOL_KWARGS": {
                "max_connections": 1000,
                "encoding": 'utf-8'
            },
            "PASSWORD": "密码"  # redis密码有密码就设置
        }
    }
}

settings.py

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    '应用程序名称',
    'channels',
]

asgi.py


import os
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application

from channels.auth import AuthMiddlewareStack
import myapi.routing

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'wyy.settings')

django_application = get_asgi_application()

application = ProtocolTypeRouter({
    "http": get_asgi_application(),
    "websocket": AuthMiddlewareStack(
        URLRouter(
            myapi.routing.websocket_urlpatterns
        )
    ),
})

应用程序/routing.py.py

from django.urls import re_path

from . import consumers

websocket_urlpatterns = [
    re_path(r'ws/chat/(?P<room_name>\w+)/(?P<user_name>\w+)/$', consumers.ChatConsumer.as_asgi()),
]

应用程序/consumers.py

import json
from channels.generic.websocket import AsyncWebsocketConsumer


class ChatConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        # 创建连接时调用
        self.room_name = self.scope['url_route']['kwargs']['room_name']
        self.user_name = self.scope['url_route']['kwargs']['user_name']
        self.room_group_name = 'chat_%s' % self.room_name
        print('roomname', self.room_name)
        print('user_name', self.user_name)
        # 将新的连接加入到群组
        await self.channel_layer.group_add(
            self.room_group_name,
            self.channel_name
        )

        await self.accept()

    async def disconnect(self, close_code):
        # 连接关闭时调用
        await self.channel_layer.group_discard(
            self.room_group_name,
            self.channel_name
        )

    # Receive message from WebSocket
    async def receive(self, text_data):
        # 收到信息时调用
        # print(1)
        print(type(text_data), text_data)
        # text_data_json = json.loads(text_data)
        # print(text_data_json)
        # message = text_data_json['message']

        # 信息群发
        await self.channel_layer.group_send(
            # text_data
            self.room_group_name,
            {
                'type': 'chat_message',
                # 'message': '{"'+self.user_name + '":"' + text_data+'"}'
                'message': {'user': self.user_name,
                            'value': text_data}

            }
        )

    # 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
        }))
最后修改:2022 年 05 月 12 日
如果觉得我的文章对你有用,请随意赞赏