• Django使用Channels实现WebSocket数据推送功能


    Django使用Channels实现WebSocket消息通知功能

    Channels 用于websocket通信,websocket是啥?主要实现在无客户端请求的情况下向客户端发送数据。

    主要概念:频道,websocket是面向频道的,就好比微信群,一个微信群就是一个频道,你向频道发送内容,微信群内的所有人(连接到这个频道的客户端)都可以收到你的消息

    本文主要写快速实现ws服务端

    需要django3.0+,最好是在linux下进行测试开发,windows下安装时问题一大堆

    • 安装:

      pip install django>=3.0
      pip install channels
      
    • 创建project

      django-admin startproject TestVideos
      
    • 创建app

      django-admin startapp chat
      
    • 创建chat/routing.py

      #django的路由叫urls.py
      #对于channels有新的路由文件
      from django.urls import re_path
      
      from . import consumers  #等同于views.py 稍后创建
      
      websocket_urlpatterns = [
          re_path(r'ws/chat/(?P<room_name>w+)/$', consumers.ChatConsumer.as_asgi()),
      ]
      
    • 创建 chat/consumers.py

      #等同于django的views.py
      #对于channels叫consumers.py
      #下面的内容作用:将新的ws客户端加入到一个频道,将其发送到ws服务端的内容广播至频道所有人
      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):
              message = dict(json.loads(text_data))
      
              # 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
              }))
      
      
    • 修改settings.py

      INSTALLED_APPS = [
          'django.contrib.admin',
          'django.contrib.auth',
          'django.contrib.contenttypes',
          'django.contrib.sessions',
          'django.contrib.messages',
          'django.contrib.staticfiles',
          ...,
          'channels',   #ws服务端
          'chat',       #ws   app
      ]
      
      
      #channels
      ASGI_APPLICATION = "TestVideos.asgi.application"    #入口信息
      CHANNEL_LAYERS = {    #频道后端,这里采用内存存储,默认是redis
          "default": {
              "BACKEND": "channels.layers.InMemoryChannelLayer"
          }
      }
      
    • 添加入口:

      配置project/asgi.py(django3.0以前仅wsgi.py。和settings.py同级)

      asgi.py原内容

      """
      ASGI config for TestVideos 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.1/howto/deployment/asgi/
      """
      
      import os
      
      from django.core.asgi import get_asgi_application
      
      os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'TestVideos.settings')
      
      application = get_asgi_application()
      
      

      asgi.py新内容

      """
      ASGI config for main_project 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.1/howto/deployment/asgi/
      """
      
      import os
      
      from django.core.asgi import get_asgi_application
      
      os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'BoatControlProject.settings')
      
      # application = get_asgi_application()  #原本内容
      
      
      from channels.routing import ProtocolTypeRouter, URLRouter  #channels
      from channels.auth import AuthMiddlewareStack
      import chat.routing    #我们创建的app
      
      
      application = ProtocolTypeRouter({
          # "http": get_asgi_application(), #此处会影响http请求。此处大概时异步接管HTTP的意思
      
          "websocket": AuthMiddlewareStack(
              URLRouter(
                  chat.routing.websocket_urlpatterns
              )
          ),
      })
      
      
      
    • 如何访问我们的ws,首先准备一个ws测试工具(用于向频道发送内容)。

      使用这个:https://github.com/easy-swoole/wstool
      
    • 在浏览器打开两个测试ws测试工具,都连接至同一个地址,client 1 发送数据, client 2 接收数据

    其他的一些功能

    • 当你有http请求或者其他地方需要向ws客户端发送内容时的写法:

      from asgiref.sync import async_to_sync
      from channels.layers import get_channel_layer
      
      @method_decorator(csrf_exempt, name="dispatch")
      class SendRoom(View):
          def dispatch(self, request, *args, **kwargs):
      
              return super(SendRoom, self).dispatch(request, *args, **kwargs)
      
          #测试频道广播
          def get(self, request, *args, **kwargs):
              event = {}
              event["message"] = {"latitudenum":37.553534,"longitudenum":122.083534,"yaw":90}
      
              channel_layer = get_channel_layer()     #重要代码
              async_to_sync(channel_layer.group_send)("chat_videos_stram", {"type": "chat_message","message": event["message"]})   #重要代码
      
              message = "ws send ok"
              return JsonResponse({"message": message})
      
          def post(self, request, *args, **kwargs):
              message = "post ok"
      
              return JsonResponse({"message": message})
      
  • 相关阅读:
    Python pip 下载速度慢? Windows 设置 国内源,用阿里云国内镜像加速
    Go timer 是如何被调度的?
    Go sync.Pool 浅析
    一次错误使用 go-cache 导致出现的线上问题
    golang面向对象分析
    一文完全掌握 Go math/rand
    这一次,彻底搞懂 Go Cond
    面试题:让你捉摸不透的 Go reslice
    当 Go struct 遇上 Mutex
    这可能是最容易理解的 Go Mutex 源码剖析
  • 原文地址:https://www.cnblogs.com/lisicn/p/14596411.html
Copyright © 2020-2023  润新知