Django - каналы 2.0: невозможно подключиться к потребителю

Я провожу несколько тестов перед переходом с каналов 1.x на 2.x; мой исходный код загружает значения файлов csv в базу данных. Однако в настоящее время я не могу установить соединение с потребителем.

settings.py

ASGI_APPLICATION = "UbiosData.routing.application"
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [("localhost", 6379)],
        },
    },
}

routing.py

from channels.routing import ProtocolTypeRouter, ChannelNameRouter
from .consumers import TestConsumer

application = ProtocolTypeRouter({
    "channel": ChannelNameRouter({
        "somename": TestConsumer,
    }),
})

потребители.py

from channels.consumer import SyncConsumer

class TestConsumer(SyncConsumer):

    def websocket_connect(self, event):
        print("websocket_connect")
        self.send({
            "type": "websocket.accept",
        })

    def websocket_receive(self, event):
        print("websocket_receive")
        self.send({
            "type": "websocket.send",
            "text": event["text"],
        })

    def test_send(self, message):
        print("Entering consumer")
        print(message["text"])

views.py

def test_channels(request):
    channel_layer = get_channel_layer()
    print(channel_layer)
    channel_layer.send("somename", {
        "type": "test.send",
        "text": "test"
    })
    return render(request, "data/data_index.html")

Результат оператора печати в функции test_channels:

RedisChannelLayer(hosts=[{'address': ('localhost', 6379)}])

Операторы печати в потребителе не выполняются, и я не получаю сообщения об ошибке. Я использую Python 3.5.3, каналы 2.0.2 и каналы-redis 2.0.2

РЕДАКТИРОВАТЬ: Вот результат, когда я запускаю сервер разработки со своим старым проектом, используя каналы 1.1.6:

Starting Channels development server at http://127.0.0.1:8000/
Channel layer default (asgi_redis.core.RedisChannelLayer)
Quit the server with CONTROL-C.
2018-02-16 16:46:48,604 - INFO - worker - Listening on channels http.request, ingest_equipment, ingest_values, websocket.connect, websocket.disconnect, websocket.receive
2018-02-16 16:46:48,606 - INFO - worker - Listening on channels http.request, ingest_equipment, ingest_values, websocket.connect, websocket.disconnect, websocket.receive
2018-02-16 16:46:48,608 - INFO - worker - Listening on channels http.request, ingest_equipment, ingest_values, websocket.connect, websocket.disconnect, websocket.receive
2018-02-16 16:46:48,609 - INFO - worker - Listening on channels http.request, ingest_equipment, ingest_values, websocket.connect, websocket.disconnect, websocket.receive
2018-02-16 16:46:48,611 - INFO - server - HTTP/2 support not enabled (install the http2 and tls Twisted extras)
2018-02-16 16:46:48,611 - INFO - server - Using busy-loop synchronous mode on channel layer
2018-02-16 16:46:48,611 - INFO - server - Listening on endpoint tcp:port=8000:interface=127.0.0.1

Вот результат, когда я запускаю сервер с новым проектом с помощью каналов 2.0.2:

Starting ASGI/Channels development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
2018-02-16 17:05:08,331 - INFO - server - HTTP/2 support not enabled (install the http2 and tls Twisted extras)
2018-02-16 17:05:08,332 - INFO - server - Configuring endpoint tcp:port=8000:interface=127.0.0.1
2018-02-16 17:05:08,334 - INFO - server - Listening on TCP address 127.0.0.1:8000

Вы заметите, что "рабочий - Прослушивание каналов" отсутствует, когда я использую каналы 2 ...


person Simon TheChain    schedule 14.02.2018    source источник
comment
Как выглядит ваш JS?   -  person The_Cthulhu_Kid    schedule 14.02.2018
comment
@The_Cthulhu_Kid На данный момент у меня не реализован Javascript, я просто пытаюсь заставить работать оператор печати.   -  person Simon TheChain    schedule 14.02.2018
comment
Извините, это моя ошибка. Я неправильно понял.   -  person The_Cthulhu_Kid    schedule 14.02.2018
comment
А от django shell пробовали?   -  person The_Cthulhu_Kid    schedule 14.02.2018
comment
@The_Cthulhu_Kid Извините, я не знаю, как это сделать, не могли бы вы уточнить?   -  person Simon TheChain    schedule 14.02.2018
comment
в вашем проекте запустите python manage.py shell, затем импортируйте get_channel_layer и запустите его, чтобы посмотреть, что он вернет.   -  person The_Cthulhu_Kid    schedule 14.02.2018
comment
@The_Cthulhu_Kid ImportError: нет модуля с именем 'get_channel_layer'   -  person Simon TheChain    schedule 14.02.2018
comment
Вам нужно импортировать его из channels так же, как вы это делаете в своем файле   -  person The_Cthulhu_Kid    schedule 14.02.2018
comment
@The_Cthulhu_Kid C:\Users\Smoky05\PycharmProjects\UbiosData\data\views.py:21: RuntimeWarning: coroutine 'RedisChannelLayer.send' was never awaited "text": "test" <HttpResponse status_code=200, "text/html; charset=utf-8">   -  person Simon TheChain    schedule 14.02.2018
comment
Вам нужно будет вникнуть в свои взгляды и посмотреть, что происходит. Я думаю, что-то не инициализируется должным образом   -  person The_Cthulhu_Kid    schedule 14.02.2018
comment
@The_Cthulhu_Kid Спасибо, теперь мне есть над чем заняться.   -  person Simon TheChain    schedule 14.02.2018
comment
Удачи с этим!   -  person The_Cthulhu_Kid    schedule 14.02.2018


Ответы (1)


Из документации: «Помните, что слои каналов поддерживают только асинхронные методы, поэтому вы можете вызывать их из собственного асинхронного контекста» или «вам нужно будет использовать async_to_sync». Поскольку потребитель, которому вы отправляете, наследуется от синхронного класса (SyncConsumer), я думаю, что второй вариант - это то, что вам нужно. Так что добавь

from asgiref.sync import async_to_sync

а затем измените

channel_layer.send("somename", {
    "type": "test.send",
    "text": "test"
})

to

async_to_sync(channel_layer.send)("somename", {
    "type": "test.send",
    "text": "test"
})

РЕДАКТИРОВАТЬ:

Да, вы точно в курсе:

Вы заметите, что "рабочий - Прослушивание каналов" отсутствует, когда я использую каналы 2 ...

Поскольку вы используете ChannelNameRouter, вам придется запустить воркер для обработки событий на вашем канале с настраиваемым именем. Сделать это можно так:

./manage.py runworker somename

и если позже вы добавите больше именованных каналов, это будет так же просто:

./manage.py runworker somename othername yetanothername

И не забудьте выполнить async_to_sync, как описано выше, это все еще необходимо.

person Luke Hebert    schedule 15.02.2018
comment
Спасибо за ответ, но ничего не вышло, результат тот же; однако это заставило меня еще раз взглянуть на мою проблему, и я кое-что обнаружил, я отредактировал свой вопрос. - person Simon TheChain; 17.02.2018
comment
Добро пожаловать и спасибо за редактирование. Я обновил свой ответ, и он должен помочь вам. Сообщите мне, если это все еще не работает. - person Luke Hebert; 17.02.2018
comment
И вы точно знаете свой ответ ;-) Я видел это в docs и попробовал, но не думаю, что запускал python manage.py runserver одновременно ... по какой-то причине ;-) Результат текущего кода: Entering consumer и test. Однако концепция синхронизации / асинхронности для меня все еще неясна, мне нужно разобраться в этом. В любом случае большое спасибо! - person Simon TheChain; 18.02.2018