Reminders for setting up an alternate python-versioned Django site on a non-root URL under WSGI on Apache

Lord help me, but that's the title I'm going with. In case it's not already obvious, you will not desire to read the following. Its existence is merely to document the tricky issues that some other sap (future-me, most likely) will encounter under a very precise set of circumstances, as enumerated in the title.

The first, and most frustipating, problem was getting mod_wsgi to use the proper Python libraries. Because I had to leave the stock Python 2.4 in place but needed 2.6 to run Django, it only dawned on me after many hours to re-configure and compile mod_wsgi with an explicit reference to the Python 2.6 version. Extra care is also needed to make sure that the other Python modules are built with the correct version and end up in the proper site-packages/ directory.

Don't forget to point to the proper Python version in the file's shebang.

The mod_wsgi documentation is a snap to read, but only once you understand it thoroughly. I eventually stumbled upon WSGIPythonPath (Edit: I meant the python-path argument to WSGIDaemonProcess, since WSGIPythonPath doesn't work in daemon mode), which did make module inclusion so much more pleasant. The more you can do with Apache directives, the more simple becomes your .wsgi file. In the end, mine was just:

import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
os.environ['PYTHON_EGG_CACHE'] = '/tmp'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

Put the .wsgi file somewhere removed from your Django app directory. Somewhere that's easily accessible to the httpd daemon, like DocumentRoot.

Running elsewhere than a web root is always dicey in Django. An extra complication is that WSGIScriptAlias gives you app it's own root URL, but that nothing in Django knows this, so you have to adjust all links with a -- preferably not hardcoded -- root path that matches the WSGIScriptAlias's setting. Same goes for STATIC_URL and ADMIN_MEDIA_PREFIX in, along with matching Apache Alias directives and Directory permissions.

Oh, and if you don't include HTTP 404 and 500 error templates, Django won't run in non-DEBUG mode. I kept seeing the error that it couldn't load a 500 template and thinking that meant it was trying to show me an actual HTTP 500 error (of which I had seen plenty thus far) and couldn't find the template to do so.

Finally, if you're not running mod_wsgi in daemon mode, you'll need to restart Apache after every source code change. I must've fixed the same problem five times in five different ways before I realized that all of my fixes had worked, but I was still viewing the old code running. Ay Caramba.

So that right there is how I spent about ten hours on New Year's Day.

Archived Comments

  1. Graham Dumpleton on 20120103.Tuesday:
    For reference, the source code reloading behaviour is described in:
  2. Dave on 20120103.Tuesday:
    Thanks, Graham. I referred to your own WSGI articles a number of times and they helped me out of a couple of jams. Much appreciated.