Django Channels – Introduction and Basic Setup
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.
- 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
Now start a Django project and create an app named ‘liveCalculator’
django-admin startproject sampleProject cd sampleProject python3 manage.py startapp liveCalculator
In sampleProject/settings.py, register channels and liveCalculator.
INSTALLED_APPS = [ 'channels', 'liveCalculator', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ]
In sampleProject/asgi.py, add the http protocol.
Now we need to register this asgi into our application. Add this line in sampleProject/settings.py :
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:
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/views.py :
Next, we need to create a route for this view. Add a new file urls.py in liveCalculator directory and add the following code:
Register this route in sampleProject/urls.py :
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 consumers.py in liveCalculator folder and add the following code:
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 routing.py in the same folder and add the following code to it:
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 routing.py into asgi.py by declaring the WebSocket protocol.
We are almost done with our first Channels application. Save all the files and run the following commands in the terminal:
python3 manage.py makemigrations python3 manage.py migrate python3 manage.py 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.