【问题标题】:sending response to particular django websocket client from rest api or a server从rest api或服务器向特定的django websocket客户端发送响应
【发布时间】:2019-08-02 23:12:26
【问题描述】:
consumer.py

    # accept websocket connection
    def connect(self):
    self.accept()

    # Receive message from WebSocket
    def receive(self, text_data):
     text_data_json = json.loads(text_data)
     command = text_data_json['command']
     job_id = text_data_json['job_id']
     if command == 'subscribe':
        self.subscribe(job_id)
     elif command == 'unsubscribe':
        self.unsubscribe(job_id)
     else:
        self.send({
            'error': 'unknown command'
        })

   # Subscribe the client to a particular 'job_id'
   def subscribe(self, job_id):
    self.channel_layer.group_add(
        'job_{0}'.format(job_id),
        self.channel_name
    )       

   # call this method from rest api to get the status of a job
   def send_job_notification(self, message, job_id):
    channel_layer = get_channel_layer()
    group_name = 'job_{0}'.format(job_id)
    channel_layer.group_send(
    group_name,
    {
        "type": "send.notification", 
        "message": message, 
    }
)   

# Receive message from room group
def send_notification(self, event):
    message = event['message']
    # Send message to WebSocket
    self.send(text_data=json.dumps(
     message))

在上面的代码中,我要做的是将客户端连接到套接字,并通过使用“订阅”方法创建一个名为“job_1”的组并将其添加到通道层,将客户端订阅到特定的“job_id”。组的创建是动态的。

我正在使用来自 Google 的“简单 websocket 客户端扩展”来连接到上面的 websocket。我能够与 websocket 建立连接并向其发送请求,如下图所示。

现在,由于客户端已连接并订阅了特定的“job_id”, 我正在使用“邮递员”向订阅特定“job_id”的上述连接客户端(简单的 websocket 客户端扩展)发送通知,方法是在请求中传入 job_id,如下面的黄色突出显示。

当我向“REST-API”发帖时,我正在调用“consumer.py”文件的“send_job_notification(self,message,job_id)”方法以及图片中显示的“job_id”为“1”下面是黄色的

完成所有这些操作后,我看不到任何发送到连接的客户端的消息,该客户端订阅了来自“REST-API”调用的“job_id”。

任何帮助都将受到高度赞赏,因为它已经拖延了很长时间。

编辑:

感谢 Ken 的建议,将方法设为“@staticmethod”是值得的,但 Ken 如何让 API 向连接的客户端发送作业状态更新,因为我的长时间运行的作业将在某些进程中运行并发送更新消息通过 REST-API 返回后端,然后需要将更新发送到正确的客户端(通过 websockets)。

我对套接字使用者的 API 调用如下:

from websocket_consumer import consumers class websocket_connect(APIView): def post(self, request, id): consumers.ChatConsumer.send_job_notification("hello",id)

我的套接字消费者代码如下:

编辑

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

}` 如您所见,“Redis”服务也在运行

Edit-1

【问题讨论】:

  • 你能把调用消费者方法的REST API中的代码贴出来吗?
  • 强烈建议不要在此处发布屏幕截图,因为人们很难复制您的代码并进行尝试。请改为发布格式化代码
  • 再次,我发现很难理解您的问题。您想发送工作状态更新吗?你如何获得更新?您可以通过调用 send_job_notification 并将作业状态/进度作为消息传递来从执行作业的进程中发送它们。但同样,我可能没有正确理解你
  • 我尝试格式化代码 Ken 但编辑器抛出错误,所以我添加了屏幕截图。是的,你是对的,我从执行工作的过程中获取更新,这些更新被提供给 API,然后 API 调用 'send_job_notification' 作为参数传递 'message' 和 'job_id' 以将作业通知发送到连接'websocket' 客户端。希望你能理解。
  • 太棒了。那么,如果您已经弄清楚了,那么您的问题是什么?问题是屏幕截图中的错误吗?如您所见,您需要删除额外的`,并且还需要导入json包

标签: python-3.x websocket redis django-channels


【解决方案1】:

您不能直接从外部代码调用使用者中的方法,因为您需要将特定的使用者实例连接到您的客户端。这是通过使用消息传递系统或代理作为 reddis 实现的通道层的工作。 从我所见,您已经朝着正确的方向前进,除了 send_job_notification 是一个需要实例化使用者的实例方法。改为静态方法,这样你就可以直接调用它而无需消费者实例

@staticmethod
def send_job_notification(message, job_id):
    channel_layer = get_channel_layer()
    group_name = 'job_{0}'.format(job_id)
    channel_layer.group_send(
    group_name,
    {
        "type": "send.notification", 
        "message": message, 
    }

在您的 API 视图中,您可以简单地将其称为: ChatConsumer.send_job_notification(message, job_id)

【讨论】:

  • 请将代码添加到原帖中,并正确格式化,以便阅读。另外,不要发布错误的屏幕截图。而是发布回溯,因为那样不可读
  • Ken 正如建议的那样,我已经编辑了原始帖子,您可以看看。我已在“编辑:”下标记了更改:
猜你喜欢
  • 1970-01-01
  • 2023-03-07
  • 1970-01-01
  • 1970-01-01
  • 2022-07-15
  • 2018-10-25
  • 1970-01-01
  • 1970-01-01
  • 2018-02-08
相关资源
最近更新 更多