Open In App
Related Articles

Django Channels – Introduction and Basic Setup

Improve Article
Save Article
Like Article

Django is a powerful Python framework for web development. It is fast, secure, and reliable. Channels allow Django projects to handle HTTP along with asynchronous protocols like WebSockets, MQTT, chatbots, and more. 


Channels preserve the synchronous behavior of Django and add a layer of asynchronous protocols allowing users to write the views that are entirely synchronous, asynchronous, or a mixture of both. Channels basically allow the application to support “long-running connections”. It replaces Django’s default WSGI with its ASGI.


ASGI (Asynchronous Server Gateway Interface) provides an interface between async Python web servers and applications while it supports all the features provided by WSGI.


A consumer is a basic unit of Channels. It is an event-driven class that supports both async and sync applications. Consumers can run longer and hence they support web sockets that need persistent connection.

In this post, we will set up a basic example of channels. We will build a calculator app that will allow the user to send multiple expressions to the server and receive the result through a single persistent connection.

Environment Setup:

  • It is always a good idea to create a virtual environment for the python apps in order to avoid version conflicts. Run the following commands in the terminal to get started
easy-install pip
python3 -m pip install virtualenv
virtualenv venv
source venv/bin/activate
  • Now install Django and Channels:
pip install django
pip install channels
# On windows, try an unofficial wheel of 'Twisted' in case of dependency errors

LiveCalculator App:

Now start a Django project and create an app named ‘liveCalculator’

django-admin startproject sampleProject
cd sampleProject
python3 startapp liveCalculator

In sampleProject/, register channels and liveCalculator.


In sampleProject/, add the http protocol.


import os
import django
from channels.http import AsgiHandler
from channels.routing import ProtocolTypeRouter
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'sampleProject.settings')
application = ProtocolTypeRouter({
  "http": AsgiHandler(),
  # Just HTTP for now. (We can add other protocols later.)

Now we need to register this asgi into our application. Add this line in sampleProject/ :

ASGI_APPLICATION = "sampleProject.asgi.application"

Create a new folder liveCalculator/templates/liveCalculator and create a new file index.html inside it. It will be the starting page of our app. Add the following code in index.html:



<!DOCTYPE html>
<html lang="en">
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Live Calculator</title>
    <textarea name="ta" id="results" cols="30" rows="10">
    Enter the expression: <input type="text" id="exp">
    <input type="button" id="submit" value="Get Results">
        const socket = new WebSocket('ws://localhost:8000/ws/livec/');
        socket.onmessage = (e) => {
            result = JSON.parse(;
            document.getElementById("results").value += "Server: " + result + "\n";
        socket.onclose = (e) => {
            console.log("Socket closed!");
        document.querySelector('#exp').onkeyup = function (e) {
            if (e.keyCode === 13) {  // enter, return
                document.querySelector('#submit ').click();
        document.querySelector("#submit").onclick = (e) => {
            inputfield = document.querySelector("#exp")
            exp = inputfield.value
                    expression: exp
            document.querySelector("#results").value += "You: " + exp + "\n";
            inputfield.value = "";

The above code will render a text area and an input box where the user can enter the expression. It will create a socket connection that we will make later and append the received result in the text area. When the user inputs the expression, it will send the expression through a socket connection.

Now create a view to render this page in liveCalculator/ :



from django.shortcuts import render
# Create your views here.
def index(request):
    return render(request, 'liveCalculator/index.html', {})

Next, we need to create a route for this view. Add a new file in liveCalculator directory and add the following code:



from django.conf.urls import url
from . import views
urlpatterns = [
    url(r'^$', views.index, name="index"),

Register this route in sampleProject/ :



from django.contrib import admin
from django.urls import path
from django.conf.urls import include, url
urlpatterns = [
    url(r'^', include('liveCalculator.urls'))

Now we need to create the consumer for our web socket connection. We will use the generic WebsocketConsumer class to implement its event-driven methods. Create a new file in liveCalculator folder and add the following code:


import json
from channels.generic.websocket import WebsocketConsumer
class Calculator(WebsocketConsumer):
    def connect(self):
    def disconnect(self, close_code):
    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        expression = text_data_json['expression']
            result = eval(expression)
        except Exception as e:
            result = "Invalid Expression"
            'result': result

The WebsocketConsumer class supports these user-defined methods:

  • connect(): We can write the business logic of what should happen when the client sends a connection request.
  • disconnect(): We can write the business logic of what should happen when the client sends a disconnection request.
  • receive(): We can write the business logic of what should happen when the client sends a message.

It also supports these built-in methods:

  • accept(): It will accept the incoming connection.
  • close(): It will close the current connection.
  • send(): It will send the specified message to the client.

We have simply used the above methods in our Calculator class to accept the connection, evaluate the expression when a message a received, and send it to the client.

Next, we also need to define the routing method for this consumer. Create a new file in the same folder and add the following code to it:


from django.urls import re_path
from . import consumers
websocket_urlpatterns = [
    re_path(r'ws/livec/$', consumers.Calculator.as_asgi()),

Note that we have used as_asgi() method on our Calculator class to use it for our application. This will enable the socket on ws://<IP:Port>/ws/livec. Now register into by declaring the WebSocket protocol.


import os
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
import liveCalculator.routing
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "sampleProject.settings")
application = ProtocolTypeRouter({
  "http": get_asgi_application(),
  "websocket": AuthMiddlewareStack(

We are almost done with our first Channels application. Save all the files and run the following commands in the terminal:

python3 makemigrations
python3 migrate
python3 runserver

Now open http://localhost:8000 on your browser, and you should see the output like this:

See the log of the server. Note that we have created the connection only once, and we can send the message multiple times without creating a new connection. 

Last Updated : 13 Apr, 2021
Like Article
Save Article
Similar Reads
Related Tutorials