3

I have a form to input Line coordinates at 127.0.0.1:8000/dashboard/ and an "Ok" button to submit the coordinates. The coordinates are posted at 127.0.0.1:8000/api/line/ by calling the view LineDisplay(). Here I want to push the Line coordinates back to 127.0.01:8000/dashboard/.

I have done the following so far:

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:

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

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

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:

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?

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? Thanks.

1 Answer 1

5

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. A Group is just a way to collect all the message.reply_channels.

So, let's say any user who opens your /dashboard/ page will receive any new "info" item that is posted. First, you need to remember the new client's Channel. That's what your ws_add is for

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.

Of course you want to clean up after yourself, so that's what ws_disconnect is for. Remove the client once they do a WebSocket.close() or they close their browser, etc.

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

And finally, there is your 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. 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). The reason is that you could also send other data types, like blobs. 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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.