School is a twelve-year jail sentence where bad habits are the only curriculum truly learned.
John Taylor Gatto
A Django deployment guide for Ubuntu
There's a time when every Django developer has to think about deployment scenarios, when I first did it last year I thought that a setup involving Lighty, Apache, mod_proxy and mod_python was a good choice but my first approach was not the best. I put Apache as the front server, handling requests for Django generated pages and passing, via mod_proxy, requests for static content to Lighty on the back. A setup where Apache had to work even for files that wasn't supposed to serve was a very bad idea.
After many helpful comments and some more reading I realized that it was better having the server for static content on the front and Apache, which still talks to Django, on the back.
I replaced Lighty with nginx, which according to many seems to be more stable, and opted for mod_wsgi instead of mod_python to make Apache talk to Django. mod_wsgi has a lower memory overhead and it's suitable for high performance sites. There's no need for mod_proxy on Apache anymore as nginx is the one in charge of the proxy work now.
This is an easy to follow and very focused guide for developers who know how to handle their servers so I won't consider security issues, memcached, Django installation, databases or basic GNU/Linux, Apache and DNS settings. Of course all of those subjects are important and you should take care of them.
The plan
This guide includes all the steps needed to:
- Setup a domain for your Django project.
- Create a simple directory layout for Django sites.
- Configure Apache with mod_wsgi for Django.
- Configure nginx.
- Serve Django admin media files.
- Turn on the heat and show your greatest and latest Django stuff to the world.
After following all the steps you will have a Django site running with nginx on the front and Apache on the back. nginx will manage all static content and will pass Django requests to Apache and mod_wsgi.
I have tested on three Ubuntu servers (two running 8.10, Intrepid Ibex, and one 7.10, Gutsy Gibbon) but everything should be pretty similar in other GNU/Linux distributions.
Shall we start?
Regular expressions, Friedl and Kodos
Understanding and using the power of regular expressions, or simply regex, is a must for every smart programmer. Django uses them quite often on its elegant URLConf system.
I've been using regular expressions for a very long time and have read many books about them but if I have to recommend just one I'll go for the classic Mastering Regular Expressions by Jeffrey Friedl.
And nothing better to test you're on the right track while writing your own regular expressions than Kodos, a simple but nice Python based tool, easy to install from any Debian based distro with a quick sudo apt-get install kodos.
Use double quotes for {% url %} on Django
I recently commented about using the right quotes with Python and simplejson and today I found a similar issue with Django.
It happens when using the {% url %} tag on the template system in Django 1.0. {% url %} helps you to avoid hardcoding links and relies on naming your url patterns.
Let's suppose we have a url like this in our URLConf:
url(r'^add/chatroom/(?P
\w+)$', 'myapp_chatroom_add', name='myapp_chatroom_add'),
Now you could insert {% url %} in your template to get the url for a link:
{% url myapp_chatroom_add chatroom_data="abc" %}
Notice I'm passing the string "abc" using double quotes as the chatroom_data parameter.
And here's the important part, these two won't work:
{% url myapp_chatroom_add chatroom_data=abc %}
which does not use quotes at all, or this one:
{% url myapp_chatroom_add chatroom_data='abc' %}
which uses single quotes.
The errors may vary depending on how your code works but the fact is to remember that when passing string based parameters to {% url %} you need to always use double quotes.
If you're using numbers you could use either no quotes or double quotes. Single quotes will never work.
How to setup Apache, mod_python and a reverse proxy to Lighttpd for Django on Ubuntu
Update: I don't recommend this setup anymore. Use the improved setup of Django with nginx, Apache and mod_wsgi.
It's October 2008 and there's no doubt now that serious web development requires working with frameworks, software that allows us, lazy coders, to forget about repetitive tasks and focus on the specifics of each project, the stuff that makes them truly unique.
It's pretty obvious too that Django, the Python based web framework, is attracting more developers and companies lately. Guido is a googler since 2005 and the recently launched Google App Engine uses Python and Django. Seriously, there's not a better time to jump into the Django train (no pun intended RoR guys).
Experienced programmers can start writing Django applications quickly thanks to the excellent documentation and the free Django book. I've also read and can recommend Practical Django Projects, by James Bennett, part of the Django team, and Learning Website Development with Django, by Ayman Hourieh, a very smart and young Google engineer.
Django is really a web framework for perfectionists with deadlines. I'm very near to one and have almost finished coding what will be my first Django based application for Facebook. Yes, I've got a few articles about that coming soon as well.
So, everything looks great under the Sun on Djangoland? Well, there's something that bothered me since I started a few months ago: deployment on a production environment. The documentation and most books get us up and running quickly with the included development server and then just refer us to the recommended Apache and mod_python settings for more.
Unfortunately, specially if you're used to the common Linux, Apache, MySQL and PHP setup, like I was, you may be need more detailed instructions and that's why I decided to write this tutorial on how to setup Apache, mod_python and a reverse proxy to Lighttpd for Django.
Quotes causing problem with Python and simplejson
My little Django and Facebook project needed to do some JSON processing, time for using simplejson then.
My application will receive a string of JSON and transform it to a dictionary, pretty simple. Let's run a test first, starting with the Python shell, or better yet, iPython, and importing the module:
import simplejson
Now let's define a string using JSON notation and pass it to simplejson:
band = "{'name': 'Mando Diao', 'genre': 'rock and roll', 'bid': 19383}"
json = simplejson.loads(band)
And we get a ValueError exception. Let's try using simple quotes for enclosing the whole string and double quotes for the JSON keys and values:
band = '{"name": "Mando Diao", "genre": "rock and roll", "bid": 19383}'
json = simplejson.loads(band)
And there you go, no error now:
print json
{u'genre': u'rock and roll', u'bid': 19383, u'name': u'Mando Diao'}
I find a little strange that this problem happens as I've been using either type of quotes for most of my Python coding. Had you noticed this problem? I've checked simplejson's documentation and could not find anything related to this.
One last word, the new Python 2.6 includes a json module, which is a refactored simplejson. Neat.
PYTHONPATH and configuring Django with Apache and mod_python
One more post about my experience coding a Django application for Facebook. Let's discuss a little about correctly setting up Apache and mod_python.
Most of the steps are very well described on Django's documentation but you may need a few more details. Let's see.
HTTP 200 testing Django applications with Facebook
I've been writing a simple Django application for Facebook these days. I'm really enjoying how clean Django's code is and its very well thought classes and methods. It really makes web development faster.
I started with some simple HTML running locally on Django's development server and then updated my templates to output FBML based on the value of a variable I called IN_FACEBOOK and inserted into my settings.py.
After adding PyFacebook to talk to Facebook's API from Python I configured my new application according to Facebook's instructions.
Finally I changed my router's port forwarding settings to allow Facebook to see my home server's public IP, which is dynamic and provided by my ISP.
Everything ran ok up to this point and then I started noticing that after each change on my application's code Facebook returned a blank page with an HTTP 200 message.
It seemed like a connection issue and I moved the application to my real server, which has a fixed public IP, but the problem persisted. After every code change Facebook returned a blank page with the HTTP 200 message. I needed to refresh the browser three or more times to get my application loading.
My application is still on development but even so I decided to replace Django's server with an Apache and mod_python setup.
Presto¡ That was the source of the problem. It seems Django's development server response time is too high for Facebook.



Recent comments
9 weeks 3 days ago
9 weeks 6 days ago
11 weeks 1 day ago
12 weeks 3 days ago
13 weeks 2 days ago
13 weeks 5 days ago
14 weeks 3 days ago
15 weeks 19 hours ago
15 weeks 4 days ago
18 weeks 6 days ago