Django 0.9x and Django 1.x branches are so far apart that a project built on top of the former, not least when it has been rolled off into production, that porting it to the 1.x branch of Django can easily escalate into a nightmare. If you have to maintain a legacy Django project — I choose to call projects built on anything before 1.x legacy –, you will find that it is easier if you maintain two different versions of Django on your development environment. How do you do that, is the quagmire this post revolves around.
I prefer Apache with mod_python to Django’s simplistic development web-server for Django projects. Initially, the task of setting up mod_python and Apache to your tastes may seem daunting. However, once you get around its not so steep curve, the difficult task becomes second nature.
I am working with Python 2.5 on a project with Django 1.0.2. Django is deployed on the system in the site-wide default directory for third-party Python modules and applications. I also have to support development for a legacy application built on Django 0.97 (a trunk snapshot from a time long ago). My requirement is simple: I want to be able to run both projects simultaneously without having to muck around tweaking configurations besides the one time when I set the projects up.
A garden-variety solution is to change the default Django directory in the Python path to point to the specific Django that is the need of the moment. This approach puts upfront a limitation of not being able to run both projects side by side. It also is annoying because it requires tap-dancing around Django directories when switching between the two versions. It is not a considerable blow to productivity, but if it can be avoided for a better, more efficient solution, there is no reason not to.
The solution I am proposing involves having the recent Django set up as the default, with the legacy Django installed in a different directory—after all, the legacy Django is the odd item of the group. I develop on an OS X environment, where I have the two Django versions set up thus:
/Library/Python/2.5/site-packages/django
/Library/Python/2.5/site-packages/django-0.97/django
You can probably tell which is which.
I have both projects deployed as virtual hosts on Apache, each running off of the root of the web-server without stepping on the feet of the other. They can easily instead be set up to, instead of the root of the web-server, serve from under a unique sub-URL path. That is mostly a matter of preference.
For each virtual host, I have assigned a domain name based off of the name of the project. I should emphatically point out that these domains are set up to resolve to localhost on my system. They may likely have real world twins that are routable over the Internet, but for all intents and purposes, they are local to my development environment. I have done it so, partly out of convenience, and partly because one of the projects hinges on subdomain-based user-to-account mapping (what this means, simply, is that registered users on the project are assigned different accounts that directly relate to subdomains, and can log in to the project only via their respective subdomains) for proper functioning. For the latter, the domain based approach was inevitable.
With that in mind, here are the virtual host settings for the two projects
<VirtualHost *:80>
ServerAdmin root@localhost
ServerName projectone.com
<Location "/">
SetHandler python-program
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE projectone.settings
PythonPath "['/Users/ayaz/Work/',
'/Users/ayaz/Work/projectone/'] + sys.path"
PythonDebug On
</Location>
</VirtualHost>
<VirtualHost *:80>
ServerAdmin root@localhost
ServerName legacyproject.com
<Location "/">
SetHandler python-program
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE legacyproject.settings
PythonPath "['/Library/Python/2.5/site-packages/django-0.97',
'/Users/ayaz/Work/', '/Users/ayaz/Work/legacyproject/'] + sys.path"
PythonDebug On
</Location>
</VirtualHost>
While each line of the above is important, the following is the highlight of this post:
PythonPath "['/Library/Python/2.5/site-packages/django-0.97',
'/Users/ayaz/Work/', '/Users/ayaz/Work/legacyproject/'] + sys.path"
I have effectively injected the path to Django 0.97 into Python path. What this helps achieve is that when mod_python loads the Python interpreter to serve an incoming request for the project, Python analyses its path, looking for a module named django. The first successful match is under the /django-0.97 directory, which, if I have not already lulled you into sleep, is where Django 0.97 lives.
For the curious, all possible mod_python directives are documented here.
All this is a one-time headache: you pop in a pill, and forget about it. I can now type in projectone.com or legacyproject.com in the browser to get to either project.
I should mention, still and all, that I have of late come to know of virtualenv, a Virtual Python Environment builder. It may be a more proper solution than what I have proposed, but I have not yet used it myself to say more.
I hope I was able to clearly explain what I had intended to.