Primary image for Using Django Inside the Tornado Web Server

Using Django Inside the Tornado Web Server

Inspired by Eric Florenzano’s talk, Using Django in Non-Standard Ways (slides in PDF) at DjangoCon and the announcement of Tornado (tornadoweb.org), I decided to try building a small application using the Django Form library and Django ORM inside Tornado. The process proved easier than I expected, especially with Russell Keith-Magee being able to provide guidance on demand.

Step 1: Create Your Database

While Russell explained that it should be possible to get commands like syncdb running outside of a traditional Django project, it was outside the scope of this small experiment. Instead, I created a Sqlite database manually. For those of you that have forgotten how to do this, this will get you started:

# sqlite3 dev.db

sqlite> CREATE TABLE message (id integer primary key, subject varchar(30), content varchar(250));
sqlite> insert into message values(1, 'subject', 'cool stuff');
sqlite> SELECT * from message;

Step 2: Write Your Application

With the database in place, you can create your application in a single file. We’ll call ours dj_tornado.py.

import sys
import os

import tornado.httpserver
import tornado.ioloop
import tornado.web

# django settings must be called before importing models
from django.conf import settings
settings.configure(DATABASE_ENGINE='sqlite3', DATABASE_NAME='dev.db')

from django import forms
from django.db import models

# Define your Model
class Message(models.Model):
"""
A Django model class.
In order to use it you will need to create the database manually.

sqlite> CREATE TABLE message (id integer primary key, subject varchar(30), content varchar(250));
sqlite> insert into message values(1, 'subject', 'cool stuff');
sqlite> SELECT * from message;
"""

subject = models.CharField(max_length=30)
content = models.TextField(max_length=250)
class Meta:
app_label = 'dj'
db_table = 'message'
def __unicode__(self):
return self.subject + "--" + self.content

# Define your Form
class DjForm(forms.Form):
subject = forms.CharField(max_length=100, required=True)
content = forms.CharField()

# Define the class that will respond to the URL
class ListMessagesHandler(tornado.web.RequestHandler):
def get(self):
messages = Message.objects.all()
self.render("templates/index.html", title="My title",
messages=messages)

class FormHandler(tornado.web.RequestHandler):
def get(self):
form = DjForm()
self.render("templates/form.html", title="My title", form=form)

def post(self):
data = {
'subject':self.request.arguments['subject'][0],
'content':self.request.arguments['content'][0],
}
form = DjForm(data=data)
if form.is_valid():
message = Message(**form.cleaned_data)
message.save()
self.redirect('/')
else:
self.render("templates/form.html", title="My title", form=form)

# map the Urls to the class
application = tornado.web.Application([
(r"/", ListMessagesHandler),
(r"/form/", FormHandler),
])

# Start the server
if __name__ == "__main__":
http_server = tornado.httpserver.HTTPServer(application)
http_server.listen(8888)
tornado.ioloop.IOLoop.instance().start()

Step 3: Create Some Templates

As you have seen in the code above I am using 2 simple templates to render the responses. Tornado syntax is very similar to Django/Jinja templates so Django developers should feel right at home here.

<!-- index.html -->
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<ul>
{% for message in messages %}
<li>{{ escape(message.subject) }} -- {{ escape(message.content) }}</li>
{% end %}
</ul>
<a href='/form/'>Add</a>
</body>
</html>
<!-- form.html -->
<html>
<body>
<form action="/form/" method="post">
{{ form }}
<input type="submit" value="Submit" />
</form>
</body>
</html>

Step 4: Start Your Server

This is easy: # python dj_tornado.py

Step 5: Profit!

Point your browser to http://127.0.0.1:8888 and enjoy your toy Tornado application.

While this application itself doesn’t do much of anything exciting, it should give you a blueprint for how to use Django in “non-standard” ways and show you how to bring some of your familiar Django tools into different applications.

You can find the code example at http://bitbucket.org/yml/dj_tornado/. I would be glad hear your opinion about this approach.

Yann Malet

About the author

Yann Malet

Yann builds and architects performant digital platforms for publishers. In 2015, Yann co-authored High-Performance Django with Peter Baumgartner. Prior to his involvement with Lincoln Loop, Yann focused on Product Lifecycle Management systems (PLM) for several large …