TUTORIAL: Real-time chat with Django, Twisted and WebSockets – Part 1

[Part 1] - [Part 2] - [Part 3] - [Addendums] - [Source]
[Table of Contents]

(I make some basic assumptions about the readers of this tutorial).


We’re going to be building a very basic chat server on top of Django 1.5, and Twisted 13.1. For this implementation, we’ll be relying on Django, and Django’s html templating facility, to design, build  and to serve the ui components for the application.

Twisted will provide the actual chat functionality, over two separate channels:

  • first, we’ll have twisted serving chat to websocket connections
  • we’ll then add an http api, to demonstrate what a long-polling chat client might look like

if you haven’t already, it’s probably worth spending a few minutes making sure you have gitpipvirtualenv and virtualenvwrapper installed and working properly, and then set up an environment using Django 1.5.

Django scaffolding

create a new Django project:

bash: django-admin.py startproject django_twisted_chat

test that the project is up and running properly by starting the server:

bash: cd django_twisted_chat
bash: python manage.py runserver

and then connecting to You can check that the server is running – you’ll see a “Welcome to Django” page if it’s running properly.

Configure Django Project

edit django_twisted_chat/settings.py and add the following lines to the top:

#convenience variable, to refer to the directory the application is currently running in:
import os
BASE_DIR = os.path.dirname(os.path.abspath(__file__))

configure a database; since this is a demo, and is unlikely to ever make it to production, we’ll use sqllite and store our data to disk:

'default': {
'ENGINE': 'django.db.backends.sqlite3',
        'NAME': './sqlite_database_file',
         # The following settings are not used with sqlite3:

we’re going to be serving some static files in this demo, javascript files only for now (a more advanced version may serve images, and other static elements too), so we should tell Django where we’re storing these files. I used the default – a  “static” directory, off the base of the server and/or individual applications:

# Additional locations of static files
# Put strings here, like "/home/html/static" or "C:/www/django/static".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
    os.path.join(BASE_DIR, "static"),

We’ll also use Django’s templating facilities, so configure the server to use them:

# Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
os.path.join(BASE_DIR, 'templates'),

In a few minutes we’ll make our chat application, and we can reuse Django’s admin interface as a shortcut interface, for manually adding a few required elements to the database (ie., chat room definitions). So, let’s configure the server to serve both of those:


Make sure to save your settings file.

Set up url paths

Now, well want the Django project to properly direct http requests to our chat application, as well as to the built in admin components. To do that, edit the django_twisted_chat/urls.py file, like so:

from django.conf.urls import patterns, include, url
from django.views.generic import RedirectView
from django.contrib import admin

urlpatterns = patterns('',
     url(r'^(/)?$', RedirectView.as_view(url='/chats/')),
     url(r'^chats/', include('chat.urls')),
     url(r'^admin/', include(admin.site.urls)),

Most of this should be familiar from the Django tutorial. The only potential addition is the use of the RedirectView.as_view shorthand. This is a built in shorthand tool for redirecting requests from one url to the other; we’re using it to redirect all requests for and/or to We’ll using it here for convenience’s sake – since we’re not going to be serving anything on for now, have the server automatically redirect requests to the /chats/ application instead of returning a 404 error.

Create and configure Django Chat application

Create a Django application to serve the chat specific components:

bash: python manage.py startapp chat

for now, we’ll only worry about adding the basic components for a web-sockets based chat client. Django will serve the ui and javascript source portions, letting Twisted handle the chat api and server components. First, construct the model for a chat room -edit chat/models.py:

from django.db import models

class ChatRoom(models.Model):
    name = models.CharField(max_length=200)

    def __unicode__(self):
	return self.name

We're building a model for storing a ChatRoom. Note that this specific tutorial doesn't go so far as to store actual chat messages to disk, so we won't need a ChatMessage model (though that model is probably present in the sample code provided at the end of this sequence). That's work for a future followup.

Make sure that we have a nice UI for editing the room of existing chat rooms. For now, we'll rely on the existing admin console for Django, so, create and edit the chat/admin.py file:

from django.contrib import admin
from chat.models import ChatRoom


Next, we'll define the application specific urls, in chat/urls.py:

from django.conf.urls import patterns, url

from chat import views

urlpatterns = patterns('',
        url(r'^$', views.index, name='index'),
        url(r'^(?P\d+)/$', views.chat_room, name='chat_room'),

This is where the project urls file (django_twisted_chat/urls.py) is going to look for urls (a result of the "url(r'^chats/', include('chat.urls'))" line we wrote in there earlier).

Now, we'll need a couple of html templates for displaying chat room related information. The templates need somewhere to sit on disk, so create an app specific templates directory:

bash: mkdir chat/templates

then, create a templates directory for the url we'll be using (we called it chats in the django_twisted_chat/urls.py file, so this directory structure is what Django will, by default, expect):

bash: mkdir chat/templates/chats

We'll have our index list all available chat rooms, so create a template for that. Edit chat/templates/chats/index.html:

{% if chat_list %}</pre>
<ul>{% for chat in chat_list %}</ul>
	<li><a id="" href="{% url 'chat_room' chat.id %}"> {{ chat.name }}</a></li>
<ul>{% endfor %}</ul>

{% else %}

No chats are available.

{% endif %}

Then create a page to serve as ui for an individual chat room. Edit chat/templates/chats/chat_room.html:

{% load staticfiles %}</pre>
<h1>{{ chat.name }}</h1>
<div id="message_list"></div>

Next, we can construct the relevant views. Edit the chat/views.py file:

from django.http import HttpResponse
from django.shortcuts import render, get_object_or_404

from chat.models import ChatRoom

def index(request):
  chat_rooms = ChatRoom.objects.order_by('name')[:5]
  context = {
    'chat_list': chat_rooms,
  return render(request,'chats/index.html', context)

def chat_room(request, chat_room_id):
  chat = get_object_or_404(ChatRoom, pk=chat_room_id)
  return render(request, 'chats/chat_room.html', {'chat': chat})

Again, this follows the basic pattern taught in the Django tutorial. The convenience method get_object_or_404 may be unfamiliar - it's a shorthand for searching for an element in the database, and automatically returning a 404 not found error if the object is missing (in this case, if someone accidentally tries to access a chat room that doesn't yet exist).

This should now give us a functional Django application. Let's make sure that it works properly, and that we don't have any typos. Create and define the structure of the database (make a super user for it when you create it), then start Django:

bash: python manage.py syncdb
bash: python manage.py runserver

Next, log in to the admin console and create a chat room. Go to:

log in with the super user that you created, and add a ChatRoom (give it a name and save it).

To test that the chat room exists and everything we've done so far is working properly, go to:

You should automatically be redirected to, and see a list of existing chat rooms.

Chat Room List

Click on one of them, and you should now see an empty chat room on your screen:

Empty chat room

For fun, try opening the chat room url in multiple browser windows, and then typing in it. Unfortunately, nothing interesting happens yet. That's where the Twisted chat server comes in - see Part 2