Quick Start - Django Channels / Channels /

Introduction

Django Channels is a fantastic piece of software that intimidates most new comers. This may be attributed to the verbose (yet fantastic) tutorial. This post aims to give you a quickstart guide to Django Channels.

We will be building a simple echo application using Django Channels. Future posts will cover more elaborate examples.

Bootstrapping

Let's install django channels then setup a django project. We're going to use the daphne as our ASGI server.

$ pip install 'channels[daphne]'
$ django-admin startproject mysite
$ cd mysite
$ python manage.py startapp core

Update your settings.py.

INSTALLED_APPS = [
    'daphne',
    'channels',
    'core',
    ...
]

ASGI_APPLICATION = "mysite.asgi.application"

Add a core/routing.py file in the core app.

from django.urls import path

websocket_urlpatterns = []

Update asgi.py in the mysite directory.

import os 
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application


os.environ.setdefault("DJANGO_SETTINGS_MODULE", "project.settings")

django_asgi_app = get_asgi_application()

from core.routing import websocket_urlpatterns

application = ProtocolTypeRouter(
    {
        "http": django_asgi_app,
        "websocket": URLRouter(websocket_urlpatterns)
    }
)

Your mysite directory should look like this.

mysite
├── manage.py
├── mysite
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── core
    ├── __init__.py
    ├── models.py
    ├── routing.py
    └── views.py

Echoing back your own message

Create an html page to test the websocket connection.

$ mkdir -p core/templates/ && touch core/templates/index.html

With the following content:

<!DOCTYPE html>
<html>
<head>
    <title>Echo</title>
</head>
<body>
    <h1>Echo Test</h1>
    <input type="text" id="message">
    <button id="send">Send</button>
    <span id="reply"></span>

    <script>
        const reply_span = document.querySelector('#reply');
        const message_input = document.querySelector('#message');
        const send_button = document.querySelector('#send');

        const host = window.location.host;
        const ws = new WebSocket(`ws://${host}/ws/echo/`);

        ws.onmessage = function(event) {
            reply_span.innerHTML += event.data;
        };

        send_button.addEventListener('click', () => {
            ws.send(message_input.value);
            message_input.value = '';
        });

    </script>
</body>
</html>

Update mysite/urls.py to load the template.

from django.urls import path

from django.views.generic import TemplateView

urlpatterns = [
    path('', TemplateView.as_view(template_name='index.html')),
]

Add the websocket consumer to the core/consumers.py file. This is the backing logic for the websocket connection.

from channels.generic import websocket


class EchoConsumer(websocket.WebsocketConsumer):
    def receive(self, text_data):
        self.send(text_data=text_data)

And update the core/routing.py file to include the websocket consumer.

from django.urls import path

from . import consumers

websocket_urlpatterns = [
    path(r"ws/echo/", consumers.EchoConsumer.as_asgi()),
]

Running the server

Run the server using:

$ python manage.py runserver

Django version 5.1.3, using settings 'project.settings'
Starting ASGI/Daphne version 4.1.2 development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Then navigate to http://127.0.0.1:8000/. You should see the echo test page. Type some text in the input box and hit "Enter", you should see the same text echoed back.

Outro

Congratulations! You have successfully setup a Django Channels project.

This post was a quickstart guide to Django Channels. We built a simple echo application to get you started. However, this will only let you communicate back and forth with the backend server, within the same browser window (not to other windows/clients). While not very useful, most of the required setup is done for future posts.

Stay tuned for more elaborate examples soon!