22
votes

I have an existing Django application with a database and corresponding models.py file.

I have a new Tornado application that provides a web service to other applications. It needs to read/write from that same database, and there is code in the models file I'd like to use.

How can I best use the Django database and models in my Tornado request handlers? Is it as simple as making a symbolic link to the models.py Django project folder, importing Django modules, and using it? I guess I'd have to do settings.configure(), right?

Thanks!

3
You could use your django setup as an api and make async http requests to it. You then wouldn't have to worry about transfering code to tornado.dm03514
Wouldnt using the django ORM be blocking in tornado? I am not sure if that is the case, more insight by someone would be appreciated.tapan
Django ORM is definately blocking.Cole Maclean
I've just thought of a possible way to bypass Django's blocking nature. Django querysets are lazy (they don't hit the database until you say so). So if you do raw = Model.objects.all().query, you get the raw SQL query which you can pass in your tornado's asynchronous db driver. Am I mistaken?hymloth

3 Answers

12
votes

Add the path to the Django project to the Tornado application's PYTHONPATH env-var and set DJANGO_SETTINGS_MODULE appropriately. You should then be able to import your models and use then as normal with Django taking care of initial setup on the first import.

You shouldn't require any symlinks.

19
votes

there is an example here about how to use django ORM and django form inside Tornado. and you can read Using Django Inside the Tornado Web Server for some information. the following code has taken from there:

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()

and this is another demo with django and tornado...

4
votes

I could not get it to work with the information provided by @aragon in Django 1.8. Since this question is one of the top results in Google when searching for Django + Tornado integration, here is how I got it to work in Django 1.8:

from django import forms
from django.db import models

from models import Operation #Own model
import django

DATABASES = {
'default': {
    'ENGINE': 'django.db.backends.sqlite3',
    'NAME': 'database.db',
    }
}
settings.configure(DATABASES=DATABASES)

if django.VERSION[:2] > (1,5):
    django.setup()