Django 频道 - 自定义路由似乎不起作用

Posted

技术标签:

【中文标题】Django 频道 - 自定义路由似乎不起作用【英文标题】:Django channels - custom routing does not seem to work 【发布时间】:2017-12-02 19:47:12 【问题描述】:

我正在努力了解 Django 的频道包,并希望尝试在同一页面上执行不同的操作时拥有更大的灵活性。我一直试图弄清楚为什么我的 webSocketBridge 不起作用,因为它看起来应该可以查看其他示例。

这是应用路由:

channel_routing = [
    route('websocket.connect', ws_connect),
    route('websocket.disconnect', ws_disconnect),
    route('websocket.receive', ws_receive),
]
custom_routing = [
    route("chat.receive", receive_chat_message, command="^send$"),
]

settings.py 读取的主路由:

channel_routing = [       
    include("ChatApp.routing.channel_routing", path=r"^/chat/stream/$"),
    include("ChatApp.routing.custom_routing"),
]

消费者,甚至没有被调用:

@channel_session_user
def receive_chat_message(message):
    log.debug("ws recieved a message")
    try:
        data = json.loads(message['text'])
    except ValueError:
        log.debug("ws message isn't json text")
        return

    if 'message' not in data:
        log.debug("ws message unexpected format data=%s", data)
        return

    if data:
        room = Room.objects.first()
        log.debug('chat message handle=%s message=%s', message.user, data['message'])
        reply = Message.objects.create(
            room=room,
            handle=message.user.username,
            message=data['message'],
        )

        Group('users').send(
            'text': json.dumps(
                'reply': reply.message,
                'handle': reply.handle,
                'timestamp': reply.formatted_timestamp
            )
        )

然后就是当前的JS绑定到这一切了:

$(function () 
  // Correctly decide between ws:// and wss://
  let ws_path = "/chat/stream/";
  console.log("Connecting to " + ws_path);

  let webSocketBridge = new channels.WebSocketBridge();
  webSocketBridge.connect(ws_path);

  webSocketBridge.listen(function(data) 
    if (data.username) 
      const username = encodeURI(data['username']);
      const user = $('li').filter(function () 
        return $(this).data('username') === username;
      );

      if (data['is_logged_in']) 
        user.html(username + ': Online');
      
      else 
        user.html(username + ': Offline');
      
    
  );

  $("#chatform").on("submit", function(event) 
    event.preventDefault();
    const $message = $('#message');
    const message = 
      'command': 'send',
      'message': $message.val()
    ;
    console.log(message);
    webSocketBridge.send(JSON.stringify(message));
    $message.val('').focus();
    return false;
  );

  // Helpful debugging
  webSocketBridge.socket.onopen = function () 
    console.log("Connected to chat socket");
  ;
  webSocketBridge.socket.onclose = function () 
    console.log("Disconnected from chat socket");
  
);

webSockedBridge.listen() 中的所有内容似乎都在做它应该做的事情,调用ws_connectws_disconnect。但是在 #chatformsubmit 上使用命令 thingy 发生的部分似乎对我不起作用。

现在它只是调用route('websocket.receive', ws_receive) 而不是自定义路由。让它使用命令缺少什么?

【问题讨论】:

【参考方案1】:

你的路由有问题:

 include("ChatApp.routing.channel_routing", path=r"^/chat/stream/$")

去掉末尾的$。

这是我的项目结构:

Project/
   project/
        ...
        routing.py
        settings.py
   app/
        ...
        routing.py

在settings.py中

CHANNEL_LAYERS = 
'default': 
    'BACKEND' : 'asgi_redis.RedisChannelLayer',
    'CONFIG': 
        'hosts': [('localhost', 6379)],
    ,
    'ROUTING': 'project.routing.channel_routing'


项目/项目/路由.py

from channels import include

channel_routing = [
    include('app.routing.channel_routing', path=r'^/chat/stream/'),
    include('app.routing.custom_routing'),
]

项目/app/routing.py

from channels import route
from .consumers import ( ws_connect,
                     ws_receive,
                     ws_disconnect,
                     receive_chat_message,
                     another_command_chat_message,
                    )

channel_routing = [
    route('websocket.connect', ws_connect),
    route('websocket.receive', ws_receive),
    route('websocket.disconnect', ws_disconnect),
]



custom_routing = [
    route('chat.receive', receive_chat_message, command="^send$"),
    route('chat.receive', another_command_chat_message, command="^cmd$"),
]

consumers.py

from channels import Channel
import json


def ws_receive(message):
    print('Message received')
    message.reply_channel.send('text':message.content['text'])

    print('Message.content:', message.content)
    print(type(message.content))

    print('Message[text]:', message['text'])
    print(type(message['text']))

    payload = json.loads(message['text'])
    payload['reply_channel'] = message.content['reply_channel']

    # receive the message and send to chat.receive channel
    # with command as a filter
    Channel('chat.receive').send(payload)


def ws_connect(message):
    print('Connection estabslihed')
    print(message.content)
    message.reply_channel.send('accept': True)

def ws_disconnect(message):
    print('Disconnecting')

def receive_chat_message(message):
    print('chat receive message with `send` command')
    print(message)
    print(message.content)

def another_command_chat_message(message):
    print('chat another command with `cmd` ')
    print(message)
    print(message.content)

【讨论】:

它没有帮助。它仍然只使用默认 ws channel_routing 中的默认接收路由。难道是因为redis设置而不是代码?

以上是关于Django 频道 - 自定义路由似乎不起作用的主要内容,如果未能解决你的问题,请参考以下文章

我的 Discord 机器人的可自定义欢迎频道功能不起作用,它看起来像是 MongoDB 的问题,但我无法弄清楚

自定义 Django 信号不起作用

为啥 react-router-dom 自定义路由不起作用?

自定义激活电子邮件在 Django 中不起作用

FMOD 用完了频道,FMOD_CHANNEL_FREE 似乎不起作用

本地主机上的 Django/Celery 多个队列 - 路由不起作用