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

更多内容请点击 我的博客 查看,欢迎来访。

Django Channels

https://channels.readthedocs.io/en/latest/installation.html

Channels改变Django在下面和通过Django的同步核心编织异步代码,允许Django项目不仅处理HTTP,还需要处理需要长时间连接的协议 - WebSockets,MQTT,chatbots,业余无线电等等。

它在保留Django同步和易用性的同时实现了这一点,允许您选择编写代码的方式 - 以Django视图,完全异步或两者混合的方式同步。除此之外,它还提供了与Django的auth系统,会话系统等的集成,使您可以比以往更轻松地将仅HTTP项目扩展到其他协议。

需求:消息实时推送消息以及通知功能,采用django-channels来实现websocket进行实时通讯。并使用supervisor启动daphne,保持websocket后台运行

应用安装

Django版本为2.2.3

pip安装channels

>pip install -U channels

Windows安装报错解决

  copying src\twisted\words\xish\xpathparser.g -> build\lib.win-amd64-3.7\twisted\words\xish
  running build_ext
  building 'twisted.test.raiser' extension
  error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools": https://visualstudio.microsoft.com/downloads/
  ----------------------------------------
  ERROR: Failed building wheel for twisted
  Running setup.py clean for twisted
Failed to build twisted
Installing collected packages: twisted, daphne, channels
  Running setup.py install for twisted ... error

解决方法,访问 https://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted 下载 .whl 格式文件手动安装。

[外链图片转存失败(img-UXikVksq-1564048730529)(https://blog.starmeow.cn_v_images/20190723131927979_25263.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]

安装

>pip install StarMeow_Backup/Twisted-19.2.1-cp37-cp37m-win_amd64.whl

# 继续安装

>pip install -U channels
>

下载太慢加上-i https://pypi.douban.com/simple/

添加到安装应用

将Channels库添加到已安装的应用程序列表中。编辑 settings.py 文件,并将channels添加到INSTALLED_APPS设置中。

INSTALLED_APPS = [
    # ...
    'channels',  # 【channels】(第1步)pip install -U channels 安装
    # ...
]

因pywin32造成重装系统的杯具

Windows开发环境中

channels添加到应用中后,WTF!!!报错,run不起来

Watching for file changes with StatReloader
Exception in thread django-main-thread:
Traceback (most recent call last):
  File "D:\Apps\Python\Python37\lib\threading.py", line 926, in _bootstrap_inner
    self.run()
  File "D:\Apps\Python\Python37\lib\threading.py", line 870, in run
    self._target(*self._args, **self._kwargs)
  File "D:\Apps\Python\Python37venv\StarMeowTest\lib\site-packages\django\utils\autoreload.py", line 54, in wrapper
    fn(*args, **kwargs)
  File "D:\Apps\Python\Python37venv\StarMeowTest\lib\site-packages\django\core\management\commands\runserver.py", line 109, in inner_run
    autoreload.raise_last_exception()
  File "D:\Apps\Python\Python37venv\StarMeowTest\lib\site-packages\django\utils\autoreload.py", line 77, in raise_last_exception
    raise _exception[1]
  File "D:\Apps\Python\Python37venv\StarMeowTest\lib\site-packages\django\core\management\__init__.py", line 337, in execute
    autoreload.check_errors(django.setup)()
  File "D:\Apps\Python\Python37venv\StarMeowTest\lib\site-packages\django\utils\autoreload.py", line 54, in wrapper
    fn(*args, **kwargs)
  File "D:\Apps\Python\Python37venv\StarMeowTest\lib\site-packages\django\__init__.py", line 24, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "D:\Apps\Python\Python37venv\StarMeowTest\lib\site-packages\django\apps\registry.py", line 83, in populate
    raise RuntimeError("populate() isn't reentrant")
RuntimeError: populate() isn't reentrant

这种情况看NSTALLED_APPS关联的app的相关包是否已安装完成。

channels注释掉后服务器能正常启动。

好吧,重装系统了,结果还是不行,虽然是因为资源管理器一打开CPU就占用100%重装的。

两台电脑有一台能正常系统,对比虚拟环境安装的包,各种升降版本,卸装应用包测试终于找到问题所在。

>pip install pywin32
Collecting pywin32
  Using cached https://files.pythonhosted.org/packages/a3/8a/eada1e7990202cd27e58eca2a278c344fef190759bbdc8f8f0eb6abeca9c/pywin32
-224-cp37-cp37m-win_amd64.whl
Installing collected packages: pywin32
Successfully installed pywin32-224

重新运行服务器,正常了!

Performing system checks...

System check identified no issues (0 silenced).
July 25, 2019 - 11:59:17
Django version 2.2.3, using settings 'StarMeow.settings'
Starting ASGI/Channels version 2.2.0 development server at http://0.0.0.0:80/
Quit the server with CTRL-BREAK.

逻辑代码

创建默认路由(主WS路由)

Channels路由配置类似于Django URLconf,因为当通道服务器接收到HTTP请求时,它告诉通道运行什么代码。
将从一个空路由配置开始。创建一个文件 StarMeow/routing.py ,并包含以下代码:

# 【channels】(第2步)设置默认路由在项目创建routing.py文件

from channels.routing import ProtocolTypeRouter

application = ProtocolTypeRouter({
   
   
    # Empty for now (http->django views is added by default)
})

设置执行路由对象(指定routing)

最后,将ASGI_APPLICATION设置为指向路由对象作为根应用程序,修改 settings.py 文件,添加:

# 【channels】(第3步)设置为指向路由对象作为根应用程序
ASGI_APPLICATION = "StarMeow.routing.application"

就是这样!一旦启用,通道就会将自己集成到Django中,并控制runserver命令。

启动channel layer:后端redis

信道层是一种通信系统。它允许多个消费者实例彼此交谈,以及与Django的其他部分交谈。
通道层提供以下抽象:
通道是一个可以将邮件发送到的邮箱。每个频道都有一个名称。任何拥有频道名称的人都可以向频道发送消息。
一组是一组相关的通道。一个组有一个名称。任何具有组名称的人都可以按名称向组添加/删除频道,并向组中的所有频道发送消息。无法枚举特定组中的通道。
每个使用者实例都有一个自动生成的唯一通道名,因此可以通过通道层进行通信。
在我们的聊天应用程序中,我们希望同一个房间中的多个聊天消费者实例相互通信。为此,我们将让每个聊天消费者将其频道添加到一个组,该组的名称基于房间名称。这将允许聊天用户向同一房间内的所有其他聊天用户发送消息。
我们将使用一个使用redis作为后备存储的通道层。要在端口6379上启动Redis服务器,首先系统上安装redis,并启动。

pip安装channels_redis

>pip install channels_redis

配置CHANNEL_LAYERS

修改 settings.py 增加配置

# 【channels】后端
CHANNEL_LAYERS = {
   
   
    "default": {
   
   
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
   
   
            "hosts": ["redis://:password@127.0.0.1:6379/0"],
        },
    },
}

确保channel layer可以与Redis通信。打开Django shell并运行以下命令:

>>> import channels.layers
>>> channel_layer = channels.layers.get_channel_layer()
>>> from asgiref.sync import async_to_sync
>>> async_to_sync(channel_layer.send)(
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值