[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:
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 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
Hi,
I am getting the following error when trying to access the http://127.0.0.1:8000/admin/ when trying to create a chat room in part 1.
Step:
Next, log in to the admin console and create a chat room. Go to:
http://127.0.0.1:8000/admin/
———————————————————————————————————————–
ImproperlyConfigured at /admin/
You’re using the Django “sites framework” without having set the SITE_ID setting. Create a site in your database and set the SITE_ID setting to fix this error.
Request Method: GET
Request URL: http://127.0.0.1:8000/admin/
Django Version: 1.6
Exception Type: ImproperlyConfigured
Exception Value:
You’re using the Django “sites framework” without having set the SITE_ID setting. Create a site in your database and set the SITE_ID setting to fix this error.
Exception Location: /usr/local/lib/python2.7/dist-packages/django/contrib/sites/models.py in get_current, line 43
Python Executable: /usr/bin/python
Python Version: 2.7.3
Python Path:
[‘/home/bhakar/Desktop/Python-2.7.6/django_twisted_chat’,
‘/usr/lib/python2.7’,
‘/usr/lib/python2.7/plat-linux2’,
‘/usr/lib/python2.7/lib-tk’,
‘/usr/lib/python2.7/lib-old’,
‘/usr/lib/python2.7/lib-dynload’,
‘/usr/local/lib/python2.7/dist-packages’,
‘/usr/lib/python2.7/dist-packages’,
‘/usr/lib/python2.7/dist-packages/PIL’,
‘/usr/lib/python2.7/dist-packages/gst-0.10’,
‘/usr/lib/python2.7/dist-packages/gtk-2.0’,
‘/usr/lib/pymodules/python2.7’,
‘/usr/lib/python2.7/dist-packages/ubuntu-sso-client’,
‘/usr/lib/python2.7/dist-packages/ubuntuone-client’,
‘/usr/lib/python2.7/dist-packages/ubuntuone-control-panel’,
‘/usr/lib/python2.7/dist-packages/ubuntuone-couch’,
‘/usr/lib/python2.7/dist-packages/ubuntuone-installer’,
‘/usr/lib/python2.7/dist-packages/ubuntuone-storage-protocol’]
Server time: Tue, 10 Dec 2013 02:37:39 +0000
hi Bhaskar,
it sounds like your django installation is not fully configured – did you run the syncdb command?
alternatively, maybe you’re running a newer version of django. the sites framework is disabled by default for django 1.6+. this tutorial is using django 1.5.
there are instructions for properly enabling the sites framework on django 1.6+ here:
https://docs.djangoproject.com/en/dev/ref/contrib/sites/
Hi ferretfarmer,
So, I was working on django 1.6 and hence I manually had to enable the sites framework. Thank you for the reply ! Now I’m running into another error. After creating two chatrooms through the admins site, I get the following :
when I acess http://127.0.0.1:8000/chats/
{{ chat.name }
{{ chat.name }
and clicking on any of the hyperlinks give an error page shown below:
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/chats/%7B%
Using the URLconf defined in django_twisted_chat.urls, Django tried these URL patterns, in this order:
1. ^(/)?$
2. ^chats/ ^$ [name=’index’]
3. ^chats/ ^(?P\d+)/$ [name=’chat_room’]
4. ^admin/
The current URL, chats/{%, didn’t match any of these.
sounds like you’re not filling the templates correctly.
are you still using django 1.6? if so, maybe the syntax for templates has changed between versions.
otherwise, your problem is probably in one of the following three files – check that you’re using the correct format for urls (did you give the urls names?):
https://github.com/aausch/django_twisted_chat/blob/master/chat/urls.py
double check that the template file you’re using is in the correct format:
https://github.com/aausch/django_twisted_chat/blob/master/chat/templates/chats/index.html
and that your views are passing in the correct template arguments:
https://github.com/aausch/django_twisted_chat/blob/master/chat/views.py
I am using Django 1.6 and I faced some errors cutting and pasting the code… I have changed ‘href=”{%”> {{ chat.name }’ for ‘href=”{{chat.id}}”> {{ chat.name }}’ in index.html and everything seems to work… well… I cannot see the same as in the last screenshot, but I think I will see it in the next part. Thanks for the tutorial!
hmm… looks like wordpress munged some of the code there. cool that you have it working – here’s a link to my github repo: https://github.com/aausch/django_twisted_chat/ – once you’re finished, you can go and check what the working (finished) code looks like there if you want
hello please help me i m getting the following error again and again
ValueError at /chats//
invalid literal for int() with base 10: ”
Request Method: GET
Request URL: http://127.0.0.1:8000/chats//
Django Version: 1.8.4
Exception Type: ValueError
Exception Value:
invalid literal for int() with base 10: ”
Exception Location: C:\Users\Rabiya Abdul Jabbar\Anaconda3\envs\dclass\lib\site-packages\django\db\models\fields\__init__.py in get_prep_value, line 985
Python Executable: C:\Users\Rabiya Abdul Jabbar\Anaconda3\envs\dclass\python.exe
Python Version: 3.4.4
Python Path:
[‘C:\\Users\\Rabiya Abdul Jabbar\\Anaconda3\\django_twisted_chat’,
‘C:\\Users\\Rabiya Abdul Jabbar\\Anaconda3\\envs\\dclass\\python34.zip’,
‘C:\\Users\\Rabiya Abdul Jabbar\\Anaconda3\\envs\\dclass\\DLLs’,
‘C:\\Users\\Rabiya Abdul Jabbar\\Anaconda3\\envs\\dclass\\lib’,
‘C:\\Users\\Rabiya Abdul Jabbar\\Anaconda3\\envs\\dclass’,
‘C:\\Users\\Rabiya Abdul Jabbar\\Anaconda3\\envs\\dclass\\lib\\site-packages’]
Server time: Sat, 27 Feb 2016 17:29:36 +0300
hey – please make sure to use the correct version of python. you’re running against python 3 🙂
I am getting the following error
need more than one value to unpack
and showing the error in the views file
return render(request,’chats/index.html’, context)
hi shiva!
are you sure you’re using the correct version of django?
Hi, I tried following this but at /chats it shows only this: {{ chat.name } on a bullet point, and when I click on it, it shows this:
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8080/chats/%7B%
Using the URLconf defined in django_twisted_chat.urls, Django tried these URL patterns, in this order:
^(/)?$
^chats/ ^$ [name=’index’]
^chats/ ^(?P\d+)/$ [name=’chat_room’]
^admin/
The current URL, chats/{%, didn’t match any of these.
Why is this happening?
hi an,
looks like there might have been a typo in your copy/paste of the code – you might have split things across lines or added spaces into some of the files, or left out a closing bracket ( {{ chat.name } is not the same as {{ chat.name }})
it’s also possible, but less likely, the problem you’re seeing is caused by using newer or different versions of some of the libraries, most likely a newer version of django. i’m especially suspicious of the 8080 port value, amongst other things.
Actually, looks like it was a typo on my side! I thought I’d fixed it already.
Thanks for catching that (again…).
WordPress seems to have eaten some of the code i wrote – I’ve corrected the page, so anyone else should be now working from correct code. If you run into more problems please let me know first, and after, if it looks like a code typo, check github (see https://github.com/aausch/django_twisted_chat/blob/master/chat/templates/chats/index.html for example) since github properly displays code and might get you unstuck 😉
Hi
I am trying to build a asynchronous chat app using django 1.8 and python. I am very new to django and find complex programming jargon hard to understand. So far your tutorial seems to provide the most comprehensive guide to building a chat app.As mentioned above I am using django 1.8 and therefore want to know if i can use this tutorial to help build my app and whether I have to make any drastic changes to the code provided in this tutorial. I hope you can help. Thanks in advance
i haven’t looked at the differences between versions of django in a while. this tutorial can tell you what you need to do, and give you examples of how to do it, but odds are good whole subsections will have to be rewritten to work correctly with django 1.8
if i ever have free time to, i might do the port to 1.8 myself. but i doubt that will happen.
Hello,
I’d like to create a chat between a user and an artificial intelligence . A little like an assistance chat . Is it possible by following your plan ?
Thanks
that’s an audacious plan! this rough tutorial can get you started – but it’s outdated. probably you’ll want to update it to use more recent versions of the libraries (and possibly something other than twisted?)
Hello ferretfarmer! I have no clue if you still manage this at all. I am having an issue in the chat\url.py code. In the line “url(r’^(\?P\d+)/$'” it is erroring saying Dangling Metacharacter Pattern Expected.
I am a super noob when it comes to regex, and I have no idea what it is doing at all. If you are still floating around this site, thank you for your time!
hey jared,
i’m occasionally still around. which version of python are you on?
~ ferretfarmer
3.4. Dang that is a quick reply. So in the time that I posted and now I learned some regex (which means my Google-fu was working hard).
So the line works by omitting “/?P” So the new line will read:
url(r’^(\d+)/$’, views.chat_room, name=’chat_room’)
Thank you for writing up this post! I really needed it for my Networking class as I am a Senior and am really lazy right now.
I will continue your tutorial! Thank you.
yeah – this tutorial was not written for Python3. expect to run into some other problems 🙂
akshually, looks like that’s a formatting snafu for wordpress. it ate some of the string. you can find the correct strings here: https://github.com/aausch/django_twisted_chat/blob/e3dbf9f443cef535ff68af56fa000a22f1d6c451/chat/urls.py
Well that is super nice! Yeah I have been hitting tiny snags because of updated Python, but nothing so far that has been breaking.
Thanks again!