简体   繁体   English

使用Django频道和WebSocket

[英]Working with django channels and websockets

I have a form to input Line coordinates at 127.0.0.1:8000/dashboard/ and an "Ok" button to submit the coordinates. 我有一个表单,用于在127.0.0.1:8000/dashboard/输入Line坐标,并单击“确定”按钮以提交坐标。 The coordinates are posted at 127.0.0.1:8000/api/line/ by calling the view LineDisplay() . 通过调用视图LineDisplay()将坐标发布在127.0.0.1:8000/api/line/上 Here I want to push the Line coordinates back to 127.0.01:8000/dashboard/ . 在这里,我想将“线”坐标推回127.0.01:8000 / dashboard /

I have done the following so far: 到目前为止,我已经完成了以下工作:

urls.py: urls.py:

from django.conf.urls import url,include
from django.contrib import admin
from . import views

urlpatterns = [
    url(r'^api/line/$',views.LineDisplay.as_view()),
]

view.py: view.py:

class LineDisplay(APIView):
"""
Display the most recent line
"""

    def get(self, request, format=None):
        lines = Line.objects.all()
        serializer = LineSerializer(lines, many=True)
        return Response(serializer.data)

    def post(self, request, format=None):
        lines = Line.objects.all()
        for line in lines:
            line.delete();
        serializer = LineSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
        info = ""
        info += "Line Coordinates are: "
        lines = Line.objects.all()
        for line in lines:
            info += "x1:" + str(line.x1)
            info += " y1:" + str(line.y1)
            info += " x2:" + str(line.x2)
            info += " y2:" + str(line.y2)
        print info
        Channel('repeat-me').send({'info': info, 'status': True})
        return Response(serializer.data, status=status.HTTP_201_CREATED)
    return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

consumers.py consumers.py

import json

# In consumers.py
from channels import Group

# Connected to websocket.connect
def ws_add(message):
    Group("chat").add(message.reply_channel)

# Connected to websocket.receive
def ws_message(message):
     print "Receive Message now"
     Group("chat").send({
        "text": json.dumps({'status': False})
    })
# Connected to websocket.disconnect
def ws_disconnect(message):
    Group("chat").discard(message.reply_channel)


def repeat_me(message):
    Group("chat").send({
    "text": json.dumps({'status': message.content['status'], 'info':      
     message.content['info']})
     })

Similarly, I have added added the following code to : routing.py 同样,我将以下代码添加到了:routing.py

from channels.routing import route
from .consumers import ws_add, ws_message, ws_disconnect, repeat_me

channel_routing = [
    route("websocket.connect", ws_add),
    route("websocket.receive", ws_message),
    route("websocket.disconnect", ws_disconnect),
    route("repeat-me", repeat_me),
]

The following lines have been added to settings.py: 以下行已添加到settings.py:

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "asgiref.inmemory.ChannelLayer",
        "ROUTING": "TrainingInduct.routing.channel_routing",
    },
}

Currently, I don't know how to deal with the group "chat". 目前,我不知道如何与“聊天”小组打交道。 I don't even need a group. 我什至不需要一个小组。 What are the remaining things to be done in order to get the line coordinates to be displayed at 127.0.0.1:8000/dashboard/ as soon as a new line is posted? 要在发布新行后立即将行坐标显示在127.0.0.1:8000/dashboard/上 ,还需要做些什么?

Note: The Line coordinates are getting properly POSTED to /api/line/ I think I might have to write a server code in order to get the data from the channel and push it back, am I right? 注意:Line坐标已经正确地发布到/ api / line /,我想可能必须编写服务器代码才能从通道中获取数据并将其推回,对吗? Thanks. 谢谢。

You need the group to collect all the Channels that should receive your info. 您需要该小组来收集所有应接收您信息的渠道。 Each connected device gets one Channel. 每个连接的设备都有一个通道。

A device's channel identifier is in the message.reply_channel . 设备的通道标识符位于message.reply_channel A Group is just a way to collect all the message.reply_channel s. 组只是收集所有message.reply_channel的一种方法。

So, let's say any user who opens your /dashboard/ page will receive any new "info" item that is posted. 因此,假设任何打开您/dashboard/页面的用户都将收到发布的任何新“ info”项目。 First, you need to remember the new client's Channel. 首先,您需要记住新客户的频道。 That's what your ws_add is for 那就是你的ws_add目的

def ws_add(message):
    Group("all-my-clients").add(message.reply_channel)

Now the client who just connected is part of the all-my-clients Group, and whatever message you send via all-my-clients , will be send automatically to that client as well. 现在,刚连接的客户端是all-my-clients组的一部分,并且您通过all-my-clients发送的任何消息也将自动发送到该客户端。

Of course you want to clean up after yourself, so that's what ws_disconnect is for. 当然,您想自己清理一下,所以这就是ws_disconnect目的。 Remove the client once they do a WebSocket.close() or they close their browser, etc. 一旦客户端执行WebSocket.close()或关闭浏览器等,请删除客户端。

def ws_disconnect(message):
    Group("all-my-clients").discard(message.reply_channel)

And finally, there is your ws_message() . 最后是您的ws_message() It receives any incoming messages. 它接收任何传入的消息。

def ws_message(message):
    # Nothing to do here, because you only push, never receive.
    pass

That's all. 就这样。 Now you can just send messages to the Group you defined above from anywhere in Django. 现在,您可以从Django中的任何位置向上面定义的组发送消息。 Just make sure you send the response in the correct format. 只要确保您以正确的格式发送响应即可。 Group().send() takes a dict with a key text that has a string value (see below). Group().send()接受dict ,该dict的键text具有字符串值(请参见下文)。 The reason is that you could also send other data types, like blobs. 原因是您还可以发送其他数据类型,例如blob。 But "text" is best for this purpose. 但是“文本”最适合此目的。

def post(self, request, format=None):
    lines = Line.objects.all()
    ...
    print info
    response_data = {'info': info, 'status': True}
    Group("all-my-clients").send({
        'text': json.dumps(response_data)
    })
    return Response(serializer.data, status=status.HTTP_201_CREATED)

That should be all. 那应该是全部。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM