In this post, I'd like to talk a little about how my staging server (called
Kaylee, after the character from Firefly), is configured
to run the multiple Django projects that I have on the go. A lot of
the other articles I have read on this subject use
mod_python but my server
is configured to use WSGI, so that's what I will be going over in this
Firstly, I use virtualenv to keep the Python environments for the different projects separate, but that's a topic in itself. This isn't a requirement, but it helps if you have dependencies that you don't want installed system-wide, or projects that use different versions of a particular package.
You can read more about virtualenv and Django here.
The directory structure for my
/opt/webapps/ directory looks something like
webapps/ |-- apache | |-- coral.conf | |-- coral.wsgi | |-- myuni.conf | `-- myuni.wsgi |-- coral | |-- env | `-- repository |-- myuni | |-- env | `-- repository
The two projects shown here are Coral Issue Tracker and
MyUni. The directory for each
project contains the virtual env for that project, and the repository. Alongside
the project folders is a directory called
apache, which holds two files for
each project: the WSGI file (
<project-name>.wsgi) and the Apache
configuration file (`
Then, in the main Apache configuration, I use a directive that includes all these files automatically:
The individual project configuration files then contain a set of simple directives almost straight from the Django deployment documentation. For example, the MyUni configuration looks like this:
WSGIScriptAlias /myuni /opt/webapps/apache/myuni.wsgi Alias /myuni/docs /opt/webapps/myuni/repository/docs/_build/html Alias /myuni/media /opt/webapps/myuni/repository/myuni/static
The WSGI files are also pretty simple, though there are a couple of things worth explaining. Here is the WSGI file for the MyUni project:
import os import sys import site os.environ['PYTHON_EGG_CACHE'] = '/tmp/myuni/egg_cache' root_dir = '/opt/webapps/myuni/env' site.addsitedir(os.path.join(root_dir, 'lib/python2.6/site-packages')) sys.path.append('/opt/webapps/myuni/repository') os.environ['DJANGO_SETTINGS_MODULE'] = 'myuni.settings' import django.core.handlers.wsgi application = django.core.handlers.wsgi.WSGIHandler()
site.addsitedir() call in the WSGI file adds the library path in the
virtual environment to the python path, by inspecting it to find all the
packages that are installed. I then append the path to the project's repository
to the path also, as is standard practice in this type of deployment.
The only other thing worth mentioning here, is the
that I add to the environment. This is required if you are using Python modules
that are packaged up as eggs, so that Apache can uncompress them in a directory
to which it can write (
/tmp/ on Ubuntu is 777 by default). If you are not
using eggs, you can skip this line out altogether. Alternatively, you can
uncompress the eggs first:
$ unzip [package].egg. You can read more about
this issue, and the workaround, here.
That's pretty much all there is to it. This setup also makes it pretty easy to deploy new versions of my projects, for which I have started using Fabric. I'll save that for another post though.
If you do things differently, then I'd love to hear about how - so please leave a comment!