Realtime Chat App using Django

As an experienced Python developer, real-time communication apps are ubiquitous, ranging from customer support chats to social networking platforms, and Django provides a robust framework for building such apps efficiently.

In this tutorial, I’ll walk you through how to build a real-time chat app in Django. I’ll share practical steps and full source code, so you can create a chat app that works smoothly and can be adapted for use in real-world scenarios, like connecting support agents with customers.

Let’s get in.

What You Need Before Starting

Before we get started, ensure you have:

  • Python 3.8+ installed
  • Django 4.x installed (pip install django)
  • Channels package installed for WebSocket support (pip install channels)
  • Redis is installed and running (used as a channel layer backend)

Read Union Operation on Django Models

Step 1: Set Up Your Django Project

First, create a new Django project and app.

django-admin startproject chatproject
cd chatproject
python manage.py startapp chatapp

Add the new app and Channels to your INSTALLED_APPS in settings.py:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'channels',          # Add Channels
    'chatapp',           # Your chat app
]

Configure Channels as the default backend by adding this to settings.py:

ASGI_APPLICATION = 'chatproject.asgi.application'

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            'hosts': [('127.0.0.1', 6379)],
        },
    },
}

Step 2: Create the ASGI Application

Django’s default is WSGI, but for real-time apps, we use ASGI.

Create asgi.py in your project folder (chatproject/asgi.py):

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

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'chatproject.settings')

application = ProtocolTypeRouter({
    "http": get_asgi_application(),
    "websocket": AuthMiddlewareStack(
        URLRouter(
            chatapp.routing.websocket_urlpatterns
        )
    ),
})

Step 3: Define WebSocket Routing

Inside your app folder, create a new file routing.py:

from django.urls import re_path
from . import consumers

websocket_urlpatterns = [
    re_path(r'ws/chat/(?P<room_name>\w+)/$', consumers.ChatConsumer.as_asgi()),
]

This setup allows users to join chat rooms dynamically.

Check out Python Filter Not in Django

Step 4: Create the WebSocket Consumer

Consumers handle WebSocket connections. Create consumers.py in your app:

import json
from channels.generic.websocket import AsyncWebsocketConsumer

class ChatConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.room_name = self.scope['url_route']['kwargs']['room_name']
        self.room_group_name = f'chat_{self.room_name}'

        # Join room group
        await self.channel_layer.group_add(
            self.room_group_name,
            self.channel_name
        )

        await self.accept()

    async def disconnect(self, close_code):
        # Leave room group
        await self.channel_layer.group_discard(
            self.room_group_name,
            self.channel_name
        )

    # Receive message from WebSocket
    async def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']
        username = self.scope["user"].username if self.scope["user"].is_authenticated else "Anonymous"

        # Send message to room group
        await self.channel_layer.group_send(
            self.room_group_name,
            {
                'type': 'chat_message',
                'message': message,
                'username': username,
            }
        )

    # Receive message from room group
    async def chat_message(self, event):
        message = event['message']
        username = event['username']

        # Send message to WebSocket
        await self.send(text_data=json.dumps({
            'message': message,
            'username': username,
        }))

Step 5: Create Chat Views and Templates

In views.py of chatapp, add:

from django.shortcuts import render

def index(request):
    return render(request, 'chatapp/index.html')

def room(request, room_name):
    return render(request, 'chatapp/room.html', {
        'room_name': room_name
    })

Create URLs in chatapp/urls.py:

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('<str:room_name>/', views.room, name='room'),
]

Include these URLs in the project’s urls.py:

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('chat/', include('chatapp.urls')),
]

Read Check if Python Dictionary is Empty

Templates

Create templates/chatapp/index.html:

<!DOCTYPE html>
<html>
<head>
    <title>Chat Rooms</title>
</head>
<body>
    <h2>Enter Chat Room</h2>
    <form action="" method="get" onsubmit="goToRoom(event)">
        <input type="text" id="room-name-input" placeholder="Room name..." required>
        <button type="submit">Enter</button>
    </form>

    <script>
        function goToRoom(event) {
            event.preventDefault();
            const roomName = document.getElementById('room-name-input').value;
            window.location.href = `/chat/${roomName}/`;
        }
    </script>
</body>
</html>

Create templates/chatapp/room.html:

<!DOCTYPE html>
<html>
<head>
    <title>Chat Room - {{ room_name }}</title>
</head>
<body>
    <h2>Room: {{ room_name }}</h2>
    <div id="chat-log" style="height:300px; border:1px solid black; overflow-y:scroll;"></div>
    <input id="chat-message-input" type="text" size="100" autofocus placeholder="Type your message...">
    <button id="chat-message-submit">Send</button>

    <script>
        const roomName = "{{ room_name }}";
        const chatLog = document.getElementById('chat-log');
        const chatInput = document.getElementById('chat-message-input');
        const chatButton = document.getElementById('chat-message-submit');

        const wsScheme = window.location.protocol === "https:" ? "wss" : "ws";
        const chatSocket = new WebSocket(
            wsScheme + '://' + window.location.host + '/ws/chat/' + roomName + '/'
        );

        chatSocket.onmessage = function(e) {
            const data = JSON.parse(e.data);
            const message = document.createElement('div');
            message.innerHTML = `<strong>${data.username}:</strong> ${data.message}`;
            chatLog.appendChild(message);
            chatLog.scrollTop = chatLog.scrollHeight;
        };

        chatSocket.onclose = function(e) {
            console.error('Chat socket closed unexpectedly');
        };

        chatButton.onclick = function() {
            const message = chatInput.value;
            if (message.trim() === '') return;
            chatSocket.send(JSON.stringify({
                'message': message
            }));
            chatInput.value = '';
        };

        chatInput.addEventListener("keyup", function(event) {
            if (event.key === 'Enter') {
                chatButton.click();
            }
        });
    </script>
</body>
</html>

Step 6: Run Your Chat App

Make migrations and run the server:

python manage.py migrate
python manage.py runserver

Visit http://127.0.0.1:8000/chat/ in your browser, enter a room name, and start chatting in real-time!

I executed the above example code and added the screenshot below.

django chat application
django chat api

Read Check if Python Dictionary is Empty

Additional Tips from My Experience

  • Authentication: You can easily add user authentication to personalize chats.
  • Styling: Use CSS frameworks like Bootstrap to improve UI/UX.
  • Deployment: For production, configure Redis on your server and use Daphne or Uvicorn as ASGI servers.
  • Scaling: Channels and Redis enable horizontal scaling for many users.

Building a real-time chat app in Django is surprisingly straightforward once you grasp Channels and WebSocket concepts. This project is an excellent way to deepen your understanding of asynchronous programming in Django and build scalable communication tools.

If you want to explore more advanced features, consider adding message persistence with Django models or private messaging between users.

I hope you found this guide helpful. Happy coding!

You may like to read other Django articles:

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.