Django FastCGI

These instructions detail how to set up Django using FastCGI. Note that Dreamhost now recommends the use of Passenger WSGI for setting up Django applications, as detailed in the how-to at Django, as this approach is easier to set up and creates applications that run faster.

Prerequisites

 * FastCGI must be enabled for the site on which you intend to run Django.
 * Enable SSH access and request the default bash shell.
 * You'll need to use Subversion to download the latest version of Django's source code. (Subversion should be installed by default. Use the command 'which svn' to ensure that Subversion is already installed.)
 * Make sure that your web site works without Django and you can navigate subdirectories and see files without any problems. If you are getting the "503 Service Temporarily Unavailable" error, please read Referer Gotcha before using Django.

Setup
These instructions are based in part on Jeff Croft's article. It is assumed that you have a hosted domain such as www.mydomain.com and can create a subdomain to host media files. These instructions should work just as well if you'd rather install Django on a subdomain.

We will use the following for username, domain, and project. These should be replaced with your own details. username = myuser domain = mydomain.com media domain = media.mydomain.com project = myproject

$ mkdir django_projects $ svn co http://code.djangoproject.com/svn/django/trunk/ django_src Note: If you have previously followed the Python documentation you can run the following and not have to add anything to the PATH or follow the next 2 steps. easy_install django_src export PATH=$PATH:$HOME/django_src/django/bin export PYTHONPATH=$PYTHONPATH:$HOME/django_src:$HOME/django_projects $ source .bash_profile $ ln -s $HOME/django_src/django/contrib/admin/media $HOME/media.mydomain.com/admin_media $ cd django_projects $ django-admin.py startproject myproject $ chmod 600 myproject/settings.py DATABASE_ENGINE = 'sqlite3' DATABASE_NAME = '/home/myuser/django_projects/myproject/myproject.db' TIME_ZONE = 'US/Pacific' MEDIA_ROOT = '/home/myuser/media.mydomain.com/' MEDIA_URL = 'http://media.mydomain.com/' ADMIN_MEDIA_PREFIX = 'http://media.mydomain.com/admin_media/' Add django.contrib.admin to INSTALLED_APPS $ cd ~/mydomain.com $ wget http://svn.saddi.com/py-lib/trunk/fcgi.py import sys sys.path.insert(1, '/home/myuser/django_src') sys.path.insert(1, '/home/myuser/django_projects') from fcgi import WSGIServer from django.core.handlers.wsgi import WSGIHandler import os os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.settings' WSGIServer(WSGIHandler).run $ chmod 755 ~/mydomain.com/dispatch.fcgi ~/mydomain.com/fcgi.py RewriteEngine On RewriteBase / RewriteRule ^(dispatch\.fcgi/.*)$ - [L] RewriteRule ^(.*)$ dispatch.fcgi/$1 [L] $ ~/django_projects/myproject/manage.py syncdb $ touch ~/mydomain.com/dispatch.fcgi
 * Enable 'FastCGI Support' on mydomain.com in the Dreamhost control panel (Domains -> Manage Domains -> Web Hosting Column, Edit -> Fast CGI Support?)
 * Create a media subdomain in Dreamhost control panel, media.mydomain.com
 * Create a directory in your home directory to contain your Django projects:
 * Download the latest Django source code
 * Otherwise, without easy_install, edit .bash_profile to add Django to your path and python path
 * Reload .bash_profile
 * Link admin_media to your media domain from the Django source code
 * Start a new project in django_projects
 * Edit ~/django_projects/myproject/settings.py. SQLite is perfectly usable for test sites. If you would rather use MySQL then just edit the settings appropriately here. (For MySQL, in case your DreamHost server does not have it already, you will also have to download and [easy_]install the MySQL-Python module, or else you will see error messages)
 * Change to webroot directory for mydomain.com and download fcgi.py
 * Edit ~/mydomain.com/dispatch.fcgi
 * 1) !/usr/bin/python2.4
 * Make ~/mydomain.com/dispatch.fcgi and ~/mydomain.com/fcgi.py executable. It is important to make sure that they are not group writable, otherwise some dreamhost servers will not be able to run the scripts.
 * Edit ~/mydomain.com/.htaccess
 * Initialize the DB for your project and create an admin user
 * Load http://www.mydomain.com/ in a browser and you should see the "It worked!" page.
 * Edit ~/django_projects/myproject/urls.py and uncomment the admin lines.
 * Touch the dispatch.fcgi to reload the code
 * Load http://www.mydomain.com/admin/ in a browser and you should see the admin login page.

Run dispatch.fcgi from the commandline
It may help to find the cause of problems by manually running dispatch.fcgi from the commandline.

./dispatch.fcgi

Django should output its HTML to your shell. You can safely ignore "WSGIServer: missing FastCGI param" errors.

AttributeError: type object 'unicode' has no attribute 'decode'
This error may appear if your server defaults to Python 2.3 or earlier. Explicitly running manage.py with Python 2.4 resolves this problem: $ python2.4 manage.py

Misc.
from flup.server.fcgi import WSGIServer def test_app(environ, start_response): start_response('200 OK', [('Content-Type', 'text/plain')]) yield 'Hello, world!\n'
 * A lot of errors can be fixed by updating django and flup to the latest versions through svn.
 * Double-check your usernames, passwords, database names, and hostnames in the settings file.
 * Verify that FastCGI is working. Create a file named hello.fcgi with the following text.
 * 1) !/usr/bin/python2.4

WSGIServer(test_app).run Make sure to set the correct permissions. chmod 755 hello.fcgi


 * NOTE: For this to work, you'll still need to load up your environment (I.E. that pythonpath you'll be setting in the tutorials below). Just to verify fastcgi works, just copy the "flup" directory from your django_src (or wherever you decide to store that) over to the directory you're testing from.

Then try to load http://django.mydomain.com/hello.fcgi.


 * Once you've proven that FastCGI is working, check your sys.path settings in dispatch.fcgi. Make sure you added the directory that contains "django", and not the django directory itself! In other words, put /home/username/django_src in your sys.path, not /home/username/django_src/django.

pkill python
 * If you make changes to the code, such as working through the official tutorials, and they don't seem to work, make sure to kill any existing python processes and reload the page.

touch dispatch.fcgi
 * Also, in addition to killing the python processes, you also have to tell FastCGI that a file/code has been changed. This is pretty simple, just reupload dispatch.fcgi, or edit the file, so that the timestamp on the file will change. When Apache sees the file has been updated, it will restart your Django application for you. You can use the touch command to update the file's timestamp. Just go to the site directory, where you placed your dispatch.fcgi file and use the touch command:

Various import errors when running Django 1.7
Django 1.7 mandates calling of django.setup method.

To get rid of the errors, add import django

django.setup

before WSGIServer(WSGIHandler).run line in your dispatch.fcgi file.

mod_rewrite
To be able to login and actually use the django admin pages you will need to set up a mod_rewrite rule in your .htaccess file.

If you want everything to be run by dispatch.fcgi, you can use the following set of rewrite rules. Order is important!

RewriteEngine On RewriteBase / RewriteRule ^(media/.*)$ - [L] RewriteRule ^(appmedia/.*)$ - [L] RewriteRule ^(dispatch\.fcgi/.*)$ - [L] RewriteRule ^(.*)$ dispatch.fcgi/$1 [L]

All directories and files not managed by Django, should go before the last line. E.g., if you want to use Analog 6.0 web stats application (supplied by DreamHost), you should add following three lines before Django instruction (taken from Mod_rewrite):

RewriteCond %{REQUEST_URI} ^/stats/(.*)$ [OR] RewriteCond %{REQUEST_URI} ^/failed_auth.html$ RewriteRule ^.*$ - [L]

For example, if you want to add favicon.ico, which can be actually located in appmedia/favicon.ico:

RewriteRule ^(favicon\.ico)$ appmedia/favicon.ico [L]

And so on.

1st part of rewrite rule is a regex pattern to be matched. 2nd part is a replacement ("-" means don't rewrite the url). 3rd part is a command ("L" means "last" => "this is the last rule, quit rewriting after successful application of this rule").

Media Files
For the admin pages to be able to access the correct CSS and JavaScript files, you'll need to set up a media directory.

ln -s $HOME/django_src/django/contrib/admin/media $HOME/django.mydomain.com/admin_media

Now surfing to http://django.myproject.com/media/ should give you a directory listing: css img js

(It is possible to rename the effective name of the media directory for the admin app through a conf setting. This will be required if you decide that you want your own media in a subdirectory named 'media'.)

Helpful Links

 * Jeff Croft - Django and Dreamhost
 * Full featured deployment script for Django on dreamhost