【问题标题】:Addition Django Channels to DRF将 Django 频道添加到 DRF
【发布时间】:2021-12-11 04:47:15
【问题描述】:

我正在尝试向我的项目添加频道以发送下载状态百分比。我有一个方法download_file(),它从多个端点将文件下载到服务器。

我必须在项目中添加频道,但它是一个没有前端的 API。

asgi.py

import os
import django

from django.core.asgi import get_asgi_application

from src.apps import api
from channels.routing import ProtocolTypeRouter, URLRouter

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'src.settings')
django.setup()


application = ProtocolTypeRouter({
    'http': get_asgi_application(),
    'websocket': URLRouter(api.routing.websocket_urlpatterns),
})

settings.py

THIRD_PARTY_APPS = (
    '...' ,
    'channels',
)

# ...

# channels
ASGI_APPLICATION = 'src.asgi.application'

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_rabbitmq.core.RabbitmqChannelLayer",
    },
}

routing.py

from django.urls import path

from src.apps.api.consumers import DownloadStateConsumer

websocket_urlpatterns = [
    path('download_state/', DownloadStateConsumer.as_asgi()),
]

consumers.py

from channels.generic.websocket import AsyncWebsocketConsumer

class DownloadStateConsumer(AsyncJsonWebsocketConsumer):
    async def connect(self):
        await self.accept()

    async def receive(self, text_data=None, bytes_data=None, **kwargs):
        await self.send_json({'message': text_data})

file_download.py

def download_file():
    # ...
    response = requests.get(link.link, stream=True)
    total_length = response.headers.get('content-length')
    size = 0
    with response as r:
        r.raise_for_status()
        with open(filename, 'wb') as f:
            state = -1
            for chunk in r.iter_content(chunk_size=8192):
                size += len(chunk)
                f.write(chunk)
                done = int(100 * size / int(total_length))
                sys.stdout.write("\r%s%s" % (str(done), "%"))
                if done != state:         
                    async_to_sync(
                        get_channel_layer().group_send(
                            'download_state', {
                                'type': 'send.percent',
                                'message': done,
                            }
                        )
                    )
                    state = done
                sys.stdout.flush()
# ...

我知道在客户端上的脚本应该是这样的

const webSocket = new WebSocket(
    'ws://'
    + window.location.host
    + '/download_state/'
);

webSocket.onmessage = function(e) {
    const data = JSON.parse(e.data);
    document.querySelector('#download-state').value = data.message;
};

webSocket.onclose = function(e) {
    console.error('Chat socket closed unexpectedly');
};

问题是如何从download_file()方法发送到客户端下载状态?当前的方式不起作用 - 客户端不接收消息。谢谢!

【问题讨论】:

    标签: python django-rest-framework websocket django-channels channels


    【解决方案1】:

    最终我改为channels_redis而不是channels_rabbitmq

    CHANNEL_LAYERS = {
        'default': {
            'BACKEND': 'channels_redis.core.RedisChannelLayer',
            'CONFIG': {
                "hosts": [('127.0.0.1', 6379)],
            },
        },
    }
    

    我在指定端口上将 redis 映像运行到 Docker 中,现在它可以工作了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-28
      • 2019-10-23
      • 1970-01-01
      • 2022-09-29
      • 1970-01-01
      • 2022-07-16
      • 2021-12-02
      • 1970-01-01
      相关资源
      最近更新 更多