SitePoint
  • Premium
  • Library
  • Community
  • Save on SaaS
  • Jobs
  • Blog
LoginStart Free Trial
Preface
1

Django Channels for Real-time Updates

What this setup will do is run our application with ASGI, and make the path http://localhost:8000/ws/polls/1 (and http://localhost:8000/ws/polls/2, and so on) available as a WebSocket, to which our front end can then connect.

Channels works by providing an asynchronous equivalent of Django views. These are called consumers. So we next need to create a consumer, which we named PollsConsumer above. In polls/consumers.py, add this:

Code snippet

from channels.generic.websocket import WebsocketConsumer
class PollsConsumer(WebsocketConsumer):    def connect(self):        self.accept()
    def disconnect(self, close_code):        pass
    def receive(self, text_data):        "Handle incoming WebSocket data"
        # I hate the dreadful hollow behind the little wood,        # Its lips in the field above are dabbled with blood-red heath,        # The red-ribb'd ledges drip with a silent horror of blood,        # And Echo there, whatever is ask'd her, answers "Death."        if text_data == "echo":            self.send(text_data="death")

At this point, you should be able to start your development server with python3 manage.py runserver as normal, and everything will work just as it did before; nothing about your normal Django views is altered by running under ASGI. It’s just that now we have asynchronous behavior available to us!

A WebSocket is a permanent, long-lived, two-way connection between the client and the server. This means that the client can send messages back to the server through the WebSocket, and the server can send messages to the client. When the client messages the server, that message is received in the receive method of the consumer. In the above example, we check the text_data that is received from the client, and if it’s "echo", then we respond with "death". This is useful as a “ping”, to check that everything is working. On the client, therefore, we can use a small amount of JavaScript to set up and connect to that WebSocket, and try sending it the "echo" message to confirm we get a real-time response.

In polls/templates/polls/results.html, add a small amount of JavaScript:

Code snippet

<script>let QUESTION_ID = '{{ question.id }}';let updateSocket;
function connectSocket() {    updateSocket = new WebSocket(        'ws://' + window.location.host +        '/ws/polls/' + QUESTION_ID);
    updateSocket.onmessage = function(e) {        console.log("Received a message from the socket:", e.data);    };
    updateSocket.onclose = function(e) {        console.error('Chat socket closed unexpectedly; reconnecting');        setTimeout(connectSocket, 1000);    };
    updateSocket.onopen = function(e) {        console.log("Socket connected; sending a ping");        updateSocket.send("echo");    }}connectSocket();</script>

This script connects to the appropriate WebSocket for these results, and sends an "echo" ping to it. If you visit http://localhost:8000/polls/1/results/ and look in the browser console, you should see this:

Code snippet

Socket connected; sending a pingReceived a message from the socket: death
End of PreviewSign Up to unlock the rest of this title.

Community Questions

Previous
Finish