Revolutionize Your Chat App with Django Channels: Unleashing Real-Time Communication Power!

Intermediate developer exploring Python Django. In-depth insights, tutorials & tips. Unlocking the potential of web development. #Python #Django #WebDevelopment
Check out my previous blog about Create A Hello World! Application Using Django Framework.
Introduction
Django Channels, an extension to Django, empowers developers to build real-time applications with ease. In this step-by-step guide, We will explore how to leverage Django Channels to create a chat application that revolutionizes communication.
Get ready to take your chat app to the next level!
Prerequisites
Before diving into this tutorial, ensure that you have the following prerequisites in place:
Basic understanding of Python and Django Framework.
Python (version 3.6 or above) and pip installed on your system.
Familiarity with the Django framework and its concepts.
[Note: Use Virtual Environment For Good. 👍 ]
Steps
1. Setup and Installation
To get started, follow these steps to set up the Django framework:
Install Django Framework using pip:
pip install django
Create a new Django project:
django-admin startproject myproject
Create a new Django app within your project:
cd myproject
python manage.py startapp myapp
2. Installation and Config of Channels
I. Installation of channels
Channels are available on PyPI — to install it run:
pip install -U channels["daphne"]
Check out the Best Channels Documentation.
II. Configuration of settings.py
Open myproject/settings.py and update the below:
INSTALLED_APPS = [
# 👇 1. Add the below line
"daphne",
'django.contrib.admin',
# ....
# ...
# ..
# .
'myapp',
]
TEMPLATES = [
{
# 👇 2. Add the below line for templates
'DIRS': ['templates'],
# ....
# ...
# ..
# .
},
]
# 👇 3. Comment the below line
# WSGI_APPLICATION = 'myproject.wsgi.application'
# 👇 4. Add the below line for asgi config
ASGI_APPLICATION = 'myproject.asgi.application'
# 👇 5. Add the below line for channel layer
CHANNEL_LAYERS = {
'default': {
'BACKEND': "channels.layers.InMemoryChannelLayer"
}
}
I. INSTALLED_APPS:
The
INSTALLED_APPSvariable in Django's settings.py file lists all the Django applications installed in your project.By adding
"daphne"to theINSTALLED_APPS, you are including the Daphne ASGI server as part of your project. Daphne is a high-performance ASGI server that Django Channels can use to handle WebSocket connections.
II. TEMPLATES:
The
TEMPLATESvariable in settings.py defines a list of dictionaries containing options for Django's template engine.By adding
DIRSto the first dictionary, you specify the directories where Django should look for template files.In this case,
['templates']indicates that Django should search for template files in a directory called "templates" within your project.
III. WSGI_APPLICATION:
The
WSGI_APPLICATIONsetting specifies the WSGI application that Django uses to handle HTTP requests.By commenting out the line (
# WSGI_APPLICATION = 'myproject.wsgi.application'), you are disabling the default WSGI application configuration.
IV. ASGI_APPLICATION:
The
ASGI_APPLICATIONsetting specifies the ASGI application that Django uses to handle WebSocket connections and other asynchronous operations.By adding
ASGI_APPLICATION = 'myproject.asgi.application', you are pointing Django to the ASGI application located in the "core" directory with the filename "asgi.py".
V. CHANNEL_LAYERS:
The
CHANNEL_LAYERSsetting configures the communication layer used by Django Channels for WebSocket handling.By defining
'BACKEND': "channels.layers.InMemoryChannelLayer"under the'default'key, you are using the in-memory channel layer provided by Django Channels for development purposes.In production, you would typically use a more robust channel layer backend, such as Redis or RabbitMQ.*
These configuration changes are necessary for integrating Django Channels into your project and enabling real-time communication through WebSocket connections.
III. Configuration of asgi.py
Open myproject/asgi.py and update the below:
import os
# 👇 1. Update the below import lib
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator
from myapp.routing import websocket_urlpatterns
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
# 👇 2. Update the application var
application = ProtocolTypeRouter({
"http": get_asgi_application(),
"websocket": AllowedHostsOriginValidator(
URLRouter(
websocket_urlpatterns
)
),
})
I. Importing Libraries:
The
import osstatement imports theosmodule, which provides a way to interact with the operating system.The updated line (
from django.core.asgi import get_asgi_application) imports theget_asgi_applicationfunction from thedjango.core.asgimodule. This function returns the ASGI application object for your Django project.
II. Setting the Django Settings Module:
The line
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')sets the environment variableDJANGO_SETTINGS_MODULEto specify the location of your Django project's settings.In this example, it is set to
'myproject.settings', assuming your project's settings module is located in themyprojectdirectory.
III. Defining the application Variable:
The
applicationvariable is a key component in the ASGI (Asynchronous Server Gateway Interface) setup.The
ProtocolTypeRouterclass from thechannels.routingmodule is used to define a dictionary-based protocol router that routes different protocols to appropriate applications.
In this case, the router is defined with two keys:
"http": The HTTP protocol is routed to theget_asgi_application()function, which returns the ASGI application object for handling HTTP requests."websocket": The WebSocket protocol is routed to theAllowedHostsOriginValidator, which is used for validating the origin of incoming WebSocket connections. It wraps theURLRouterand allows connections from allowed hosts.The
URLRouteris initialized withwebsocket_urlpatternsimported from themyapp.routingmodule. This variable contains the URL patterns for WebSocket connections in your application.
These changes are made in the asgi.py file of your Django project and help configure the ASGI application to handle HTTP requests and WebSocket connections using Django Channels.
Now, let’s dive into the steps required to create a chat application using Django Channels.
3. Setting up URLs and Templates
To configure the URLs and templates in your Django project, follow these steps:
I. URL Configuration:
Open the myproject/urls.py and write the below code:
from django.contrib import admin
from django.urls import path, include # 👈 1. Add this line
urlpatterns = [
path('admin/', admin.site.urls),
# 👇 2. Add the app url on this
path('', include('myapp.urls'))
]
II. URL Configuration of views:
Create a new file urls.py inside the myapp folder and write the below code:
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index')
]
III. Added views logic:
Open the views.py file from myapp folder and write the below code for redirecting the request to an index.html template:
from django.shortcuts import render
# Create your views here.
def index(request):
return render(request, 'index.html')
IV. Template Configuration:
Create a folder named templates inside the myproject folder:
Now, open templates and create a new file base.html and write the below code:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Custom block for page title -->
<title>{% block title %}{% endblock %} | Welcome Room</title>
<!-- Bootstrap 5 CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" crossorigin="anonymous">
</head>
<body>
<!-- Custom block for content of body -->
{% block content %}{% endblock %}
<!-- Bootstrap 5 JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" crossorigin="anonymous"></script>
<!-- Custom block for javascript -->
{% block js_script %}{% endblock %}
</body>
</html>
Now, Again create a new file index.html inside the templates folder:
{% extends 'base.html' %}
{% block title %} Home {% endblock %}
{% block content %}
<div class="container mt-5">
<h3>Welcome to Room</h3>
<div class="row">
<div class="col-lg-4">
<div class="w-100">
<div class="mb-3">
<label for="textMessage" class="form-label">Enter your message:</label>
<input type="text" class="form-control" id="textMessage">
</div>
<button id="addMessage" class="btn btn-primary rounded-1">Send</button>
</div>
</div>
<div class="col-lg-8">
<div id="messages" class="mt-4"></div>
</div>
</div>
</div>
{% endblock %}
{% block js_script %}
<script>
// setup chat scoket
const chatSocket = new WebSocket(
'ws://'
+ window.location.host
+ '/ws/chat/public_room/'
);
// on socket open
chatSocket.onopen = function (e) {
console.log('Chat socket successfully connected.');
};
// on socket close
chatSocket.onclose = function (e) {
console.log('Chat socket closed unexpectedly');
};
// on receiving message on group
chatSocket.onmessage = function(e) {
const data = JSON.parse(e.data);
const message = data.message;
setMessage(message);
};
// sending the text message to server
document.querySelector('#addMessage').onclick = function(e) {
const messageInputDom = document.querySelector('#textMessage');
const message = messageInputDom.value;
chatSocket.send(JSON.stringify({
'message': message
}));
messageInputDom.value = '';
};
// helper func setting message
function setMessage(message){
var div = document.createElement('div');
div.className = 'alert alert-success alert-dismissible fade show';
div.setAttribute('role', 'alert');
var message = document.createTextNode(message);
div.appendChild(message);
var closeButton = document.createElement('button');
closeButton.type = 'button';
closeButton.className = 'btn-close';
closeButton.setAttribute('data-bs-dismiss', 'alert');
closeButton.setAttribute('aria-label', 'Close');
div.appendChild(closeButton);
var container = document.getElementById('messages');
container.appendChild(div);
}
</script>
{% endblock %}
The provided code represents an HTML structure for a chat room interface. Let’s go through each element:
<div class=”container mt-5">: This div serves as a container for the chat room interface. Thecontainerclass provides a fixed-width container andmt-5adds a margin-top to create some spacing.<h3>Welcome to Room</h3>: This heading(h3)displays the welcome message or title for the chat room.<div class=”row”>: This div defines a row to contain two columns.<div class=”col-lg-4">: This div represents the left column in the row. It occupies 4 columns on large screens(col-lg-4 class). Adjust the class based on your layout requirements.<div class=”w-100">: This div provides a full-width container within the column.<div class=”mb-3">: This div adds some margin-bottom to create spacing.<label for=”textMessage” class=”form-label”> Enter your message:</label>: This label element displays the text “Enter your message:” and is associated with the input field below.<input type=”text” class=”form-control” id=”textMessage”>:This input element is a text input field where users can enter their messages. Theform-controlclass is used for styling purposes, and theidattribute provides an identifier for JavaScript manipulation.<button id=”addMessage” class=”btn btn-primary rounded-1">Send</button>: This button element represents a “Send” button. It has thebtnandbtn-primaryclasses for styling and therounded-1class to apply rounded corners. Theidattribute is used for JavaScript manipulation.<div class=”col-lg-8">: This div represents the right column in the row. It occupies 8 columns on large screens (col-lg-8class). Adjust the class based on your layout requirements.<div id=”messages” class=”mt-4"></div>: This div serves as a container for displaying the messages. Theidattribute is used for JavaScript manipulation, and themt-4class adds a margin-top to create spacing.
Overall, this HTML code creates a chat room interface with a welcome message, an input field for entering messages, a “Send” button, and a container for displaying the messages. The layout is structured using Bootstrap’s grid system with columns and rows.
The provided code is a JavaScript script that handles the functionality of the chat room interface. Let’s break it down:
const chatSocket = new WebSocket('ws://' +window.location.host+ '/ws/chat/public_room/');: This line creates a WebSocket connection by instantiating aWebSocketobject. It uses the URL'ws://' +window.location.host+ '/ws/chat/public_room/'to connect to the WebSocket server. Thewindow.location.hostretrieves the current host, and/ws/chat/public_room/represents the endpoint or URL path for the chat room WebSocket.chatSocket.onopen: This event listener is triggered when the WebSocket connection is successfully opened. It logs a message to the console, indicating that the chat socket is successfully connected.chatSocket.onclose: This event listener is triggered when the WebSocket connection is closed. It logs a message to the console, indicating that the chat socket was closed unexpectedly.chatSocket.onmessage: This event listener is triggered when a message is received from the WebSocket server. It parses the received data into a JavaScript object usingJSON.parse(), extracts themessageproperty from the data, and calls thesetMessage()function, passing the message as an argument.document.querySelector('#addMessage').onclick: This event listener is triggered when the "Send" button with the idaddMessageis clicked. It retrieves the value of the input field with the idtextMessage, constructs a message object with themessageproperty set to the input value, sends the message to the WebSocket server usingchatSocket.send(), clears the input field, and performs any necessary updates.function setMessage(message): This function is a helper function that sets the message in the chat interface. It creates adivelement with the classesalert,alert-success,alert-dismissible, andfade showfor styling purposes. It also appends a text node containing the message text to thedivelement. Additionally, it creates a close button (buttonelement) with the classesbtn-closeand attributesdata-bs-dismissandaria-labelfor closing the alert. Finally, it retrieves the container element with the idmessagesand appends the createddivelement to it.
Overall, this JavaScript code sets up a WebSocket connection, handles events such as socket opening, socket close, and message reception, sends messages to the server, and updates the chat interface with received messages.
4. Define routing for WebSocket connections:
WebSocket connection routing in Django Channels is the process of mapping WebSocket URLs to their corresponding consumers. When a client establishes a WebSocket connection to a specific URL, the routing mechanism determines which consumer should handle the connection.
For routing of WebSocket connections is defined in a routing.py file within the project directory.
Now, Create a new file routing.py file inside the myapp folder and write the below code:
from django.urls import re_path
from . import consumers
websocket_urlpatterns = [
re_path(r"ws/chat/public_room/", consumers.ChatConsumer.as_asgi()),
]
The
django.urlsthe module is imported to access thepathfunction, which is used for defining URL patterns.The
ChatConsumerclass (imported from the.consumersmodule) is the consumer that handles WebSocket connections for the chat functionality.websocket_urlpatternsis a list that contains URL patterns for WebSocket connections. Each pattern specifies a URL that begins withws/chat/public_room.The
paththe function is used to define the URL pattern for WebSocket connections. It takes two arguments: the URL pattern itself and the consumer that will handle the connection.ChatConsumer.as_asgi()is passed as the second argument to thepathfunction. This converts theChatConsumerclass into an ASGI application that can handle WebSocket connections.
To summarize, the code defines a URL pattern for WebSocket connections to the /ws/chat/public_room/ URL. When a client establishes a WebSocket connection to this URL, the ChatConsumer consumer is invoked to handle the connection.
5. Consumers for WebSocket connections:
In Django Channels, a consumer is a class that handles WebSocket connections and manages the communication between the server and the connected clients. Consumers are the building blocks of real-time applications built with Django Channels.
Create a new file consumers.py inside the myapp folder and write the below code:
import json
from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer
class ChatConsumer(WebsocketConsumer):
def connect(self):
self.room_name = 'public_room'
self.room_group_name = self.room_name
# Join room group
async_to_sync(self.channel_layer.group_add)(
self.room_group_name, self.channel_name
)
self.accept()
def disconnect(self, code):
# Leave room group
async_to_sync(self.channel_layer.group_discard)(
self.room_group_name, self.channel_name
)
def receive(self, text_data):
json_text = json.loads(text_data)
message = json_text["message"]
# Send message to room group
async_to_sync(self.channel_layer.group_send)(
self.room_group_name,
{
"type": "chat_message",
"message": message
}
)
def chat_message(self, event):
message = event['message']
# Send message to WebSocket
self.send(text_data=json.dumps({"message": message}))
In the code, the ChatConsumer class is a subclass of WebsocketConsumer, which is a generic implementation of a consumer provided by Django Channels. Let's break down the code and understand its functionality:
I. connect():
This method is called when a WebSocket connection is established.
The
room_nameandroom_group_namevariables are initialized to identify the chat room.The consumer joins the specified
room_group_nameby adding itself to the group usingasync_to_sync(self.channel_layer.group_add).Finally,
self.accept()is called to accept the WebSocket connection.
II. disconnect():
This method is called when the WebSocket connection is closed or disconnected.
The consumer leaves the
room_group_nameby removing himself from the group usingasync_to_sync(self.channel_layer.group_discard).
III. receive(text_data):
This method is called when the server receives data from the WebSocket connection.
The received
text_datais parsed as JSON, extracting themessagevalue.The consumer sends the received message to the entire
room_group_nameby usingasync_to_sync(self.channel_layer.group_send).
IV. chat_message(event):
This method is responsible for handling messages sent from the
room_group_nameto the WebSocket connection.It extracts the
messagefrom the event dictionary.The consumer sends the message back to the WebSocket connection by calling
self.send().
The consumer plays a crucial role in Django Channels as it manages the connection, handles incoming messages, and broadcasts messages to the relevant recipients. It provides an interface for handling events, such as connecting, disconnecting, and receiving messages, in a WebSocket-based application.
By implementing a consumer, you can define the desired behavior of your application’s WebSocket connections, enabling real-time communication and interaction between the server and connected clients.
6. Testing and Running
Now that we have set up the basic structure of our chat application using Django Channels, it’s time to test and run the app. Follow these steps:
Step 1: Open your Command-Line Interface:
Open your command-line interface and navigate to the root directory of your Django project.
To proceed, please open the terminal within the myproject folder and execute the following command:
python manage.py makemigrations
python manage.py migrate
Step 2: Start the Server:
To start the server, run the following command in your command-line interface:
python manage.py runserver
This command will launch the Django development server.
Step 3: Testing
After running the server and accessing the project interface at http://127.0.0.1:8000/ .
Open any browser and hit : http://127.0.0.1:8000/ url and you can the home page of our website looks like this:

Now, Open a new tab in another browser and hit the same url and open both tab side by side like this:

Now, with the implementation of Django Channels in our chat application, the power of real-time communication comes to life. When you send a message from one side of the chat room, it instantly appears on both sides, providing a seamless and immersive experience. This dynamic functionality fulfills our goal of fostering communication in a public room.
Imagine the possibilities! Users can engage in vibrant discussions, share ideas, and connect with others in real-time. Whether it’s a collaborative project, an online community, or a customer support channel, our chat app powered by Django Channels ensures that every message sent is received and displayed without delay, enabling smooth and interactive conversations.
Final Result,

Checkout Full Live Demo:
Now, with the implementation of Django Channels in our chat application, the power of real-time communication comes to life. When you send a message from one side of the chat room, it instantly appears on both sides, providing a seamless and immersive experience. This dynamic functionality fulfills our goal of fostering communication in a public room.
Imagine the possibilities! Users can engage in vibrant discussions, share ideas, and connect with others in real time. Whether it’s a collaborative project, an online community, or a customer support channel, our chat app powered by Django Channels ensures that every message sent is received and displayed without delay, enabling smooth and interactive conversations.
Conclusion
Congratulations! You have successfully created a chat application using Django Channels. This tutorial provided an overview of Django Channels integration into a Django project and walked you through the steps required to set up real-time communication. With Django Channels, you can expand the functionality of your chat app and bring an immersive, real-time experience to your users.
Remember to explore more features offered by Django Channels, such as handling multiple chat rooms, authentication, and message persistence, to enhance your application further.
Now, it’s time to unleash the power of Django Channels and take your chat app to new heights.
Happy Coding!
Support my passion for sharing development knowledge by making a donation to Buy Me a Coffee. Your contribution helps me create valuable content and resources. Thank you for your support!
Thank you for taking the time to read this blog about Revolutionize Your Chat App with Django Channels: Unleashing Real-Time Communication Power. I hope that you found the information presented here useful and informative.
If you have any questions or comments about the information presented in this blog, please feel free to reach out. Thank you again for reading!



