Django just isn’t designed to run under CGI.
It won’t run under OS/2, either.*
Well ok, but running Django under CGI is not impossible. It just kind of really sucks. But anyway, to prove it’s possible if not workable, here’s how I got it running on two standard cPanel shared hosts using plain old slow and clunky CGI.
virtualenv
First, install virtualenv. This makes locally managing modules fantastically easy by creating self-contained Python virtual environments. Installing couldn’t be simpler: Get the script, run the script, source your environment.
$ mkdir ~/src && cd ~/src
$ curl -LO http://bitbucket.org/ianb/virtualenv/get/tip.gz
$ tar -xvzf tip.gz
$ python virtualenv/virtualenv.py --distribute ~/python_virtualenv
New python executable in /home/joe/python_virtualenv/bin/python
Installing distribute.............................................
..................................................done.
$ source ~/python_virtualenv/bin/activate
Now, install Django using pip, which was automatically installed by virtualenv. After sourcing the virtual environment, this works from anywhere.
$ pip install Django
Downloading/unpacking Django
Downloading Django-1.1.1.tar.gz (5.6Mb): 5.6Mb downloaded
Running setup.py egg_info for package Django
Installing collected packages: Django
Running setup.py install for Django
changing mode of build/scripts-2.4/django-admin.py from 664 to 775
changing mode of /home/joe/python_virtualenv/bin/django-admin.py to 775
Successfully installed Django
If your host doesn’t block GCC, use pip to be sure your MySQL interface (MySQLdb) is up to date:
$ pip install -U MySQL-python
...
Successfully installed MySQL-python
Django requires MySQLdb version 1.2.1p2 or higher.
Yolk prints a nice, clean list of everything installed in your Python environment, install and run:
$ pip install yolk
$ yolk -l
Django - 1.1.1 - active
MySQL-python - 1.2.3c1 - active
pip - 0.6.1 - active
setuptools - 0.6c11 - active
yolk - 0.4.1 - active
At this point, I started a new Django project, assigned a database and filled in the necessary values in settings.py. I put the Django project files into the virtual environment to keep everything in the same place. This might not be the best practice, but it makes sense to me.
$ cd ~/python_virtualenv/
$ django-admin.py startproject testproject
The sane part is finished, now onto the kludgery.
Django.cgi
All the CGI shim solutions I found pointed back to a script Paul Sargent uploaded to ticket 2407 back in summer of 2006. It still works: django.cgi
Three lines need editing:
Line 1: Point the CGI’s shebang to the virtualenv Python binary.
#!/home/joe/python_virtualenv/bin/python
Line 95: Add the directory above the Django project directory to Python’s sys.path.
sys.path.append("/home/joe/python_virtualenv")
Line 97: Add the project’s settings to os.environ.
os.environ['DJANGO_SETTINGS_MODULE'] = 'testproject.settings'
htaccess
For Django to respond to URL requests, those urls need to be fed into the django.cgi script. For testing I routed everything from /django to the cgi script by adding the following lines to my top-level htaccess file:
RewriteEngine on
RewriteRule ^cgi-bin/ - [L]
RewriteRule ^django/(.*)$ /cgi-bin/django.cgi/$1 [QSA,L]
The second line isn’t necessary unless pulling Django urls from the webroot, without it, the redirects would loop.
At this point, the Django site should load from /django/… urls.
Finally, as a quick fix for admin media files, I symlinked Django’s admin media directory from my web root:
ln -s ~/python_virtualenv/lib/python2.4/site-packages/django/contrib/admin/media ~/www/media
Conclusion
I spent quite a few hours spread across a couple days researching and figuring out how to get the first install working. The second installation only took about 5 minutes from start until editing Django’s admin pages.
Running Django through CGI is possible, but it is dog slow. There appears to be some caching after the first request, but that first page load often takes an excruciatingly long time.
Further reading, possible improvements
The servers I was working with are both running the almost six year old Python 2.4.3. The wsigref module was introduced with Python 2.5. My goal was to get Django running without compiling anything since some hosts deny access to GCC.
References
These sites were helpful in figuring this out.
The two hosts I tested on were LiquidWeb and A2Hosting. Both have been excellent, dependable hosts. Neither has any Python support to speak of on their shared plans. A2 blocks access to GCC.