[Part 1] - [Part 2] - [Part 3] - [Addendums] - [Source]
[Table of Contents]
(I make some basic assumptions about the readers of this tutorial).
Overview
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 git, pip, virtualenv 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 http://127.0.0.1:8000/. 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:
DATABASES = {
'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
STATICFILES_DIRS = (
# 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:
TEMPLATE_DIRS = (
# 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:
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.admin',
'chat',
)
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
admin.autodiscover()
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 http://127.0.0.1 and/or http://127.0.0.1/ to http://127.0.0.1/chats/. We’ll using it here for convenience’s sake – since we’re not going to be serving anything on http://127.0.0.1/ 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
admin.site.register(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>
<ul>{% for chat in chat_list %}</ul>
</ul>
<ul>
<ul>
<li><a id="" href="{% url 'chat_room' chat.id %}"> {{ chat.name }}</a></li>
</ul>
</ul>
<ul>{% endfor %}</ul>
<pre>
{% 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>
<pre>
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:
http://127.0.0.1:8000/admin/
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:
http://127.0.0.1:8000/
You should automatically be redirected to http://127.0.0.1:8000/chats/, and see a list of existing chat rooms.

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

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