Knowledgebase
Using Django with FastCGI
Posted by on 02 July 2012 10:37 AM

This is to be used as a reference only. Please check out our up-to-date article using the most recent technology and processes: https://help.asmallorange.com/index.php?/Knowledgebase/Article/View/305/0/installing-django-using-virtualenv.

Using Django on ASO with FastCGI

Introduction

After much looking around at various resources and my experience on getting Django FCGI working, I thought I would post an up-to-date guide on getting Django working with ASO. Hopefully this guide will be a benefit for the ASO community.

This guide will be aimed towards Tiny account holders, but to anyone else who has more storage to play with, they can tweak some of the steps to their liking.

This guides differs in such that the setup is as close to the recommended setup on Django's deployment page for Running Django on a shared-hosting provider with Apache.

Assumptions

This guide assumes that the reader is familiar with Linux and its basic commands, a terminal, SSH, and have basic programming knowledge, preferably (hopefully) in Python. If you are confused at this point about what I am talking about, then it may be a good idea to read up on what all of this is so that you don't feel like a deer in the headlights as you proceed. Additionally, knowing a decent text editor (emacs, vim, nano, etc) is a must.

I won't go through a super detailed tutorial on some of these "basic" things such as logging into your account through SSH, changing to every single directory, and anything similar. If something is severely left out or makes the guide a complete loss, please edit where necessary.

Requirements

To perform anything that will be shown in the rest of this guide you must have shell/ssh access on your account. This can be done by submitting a support request.

Django is not really picky on what version Python you are using since the core components require anything between 2.4-2.7. However, any modules from the django.contrib package may require more recent versions of Python. I would highly recommend either Python2.6 or Python2.7 since that is better supported overall by Django and any other contributing modules. You may request a particular version to be installed by submitting a ticket. You should not request Python3.x installed since Django does not support this version due to backwards compatibility support from Python. More information can be found at the Django install faq for the curious.

If you plan on using MySQL as your database back-end, you might as well submit a ticket for the MySQLdb module for the version of Python that you have installed or requested.

Preparation

While you are waiting for your support ticket(s) to be resolved or if they are done already, we can take care of these next steps that don't require the packages being installed. If you don't have shell/ssh access, then I guess just sit tight.

First, we will create a directory where we will store Python packages/modules that we will be installing or symlink'ing to. You may set up your directories wherever you like, just make sure to keep that in mind through the rest of the guide when setting up environment variables and when I refer to this directory. I prefer to create a directory structure similar to "/usr/local" in my home directory:
mkdir -p ~/local/lib/python2.X/site-packages or /home/username/local/lib/python2.x/site-packages for the full path.

Replace "X" with your Python version that is (will be installed).

To set up your shell/ssh environment, we will edit your .bashrc and .bash_profile. The aliases and environment variables set in these files will make working with your Python and Django installs through the SSH simpler. First, open up .bashrc and add the following line:
alias python='/usr/local/bin/python2.X'or alias python='/your/path/to/python2.x'

Replace "X" with your Python version that is (will be) installed. This will execute the correct Python version you wish to use whenever you run "python" on the command line for the interpreter or when running scripts.

Now open .bash_profile to set up two environment variables so that commands become available on the command line once Django is installed and to add to the path where Python looks for installed packages/modules. Please add the following two lines:
export PATH=$PATH:$HOME/local/lib/python2.X/site-packages/django/bin
export PYTHONPATH=$PYTHONPATH:$HOME/local/lib/python2.X/site-packages


Replace "X" with your Python version that is (will be) installed. [b]NOTE:[/b] If you changed where you directories are for locally installed Python packages, these lines will differ.

You will then need to logout/re-login SSH for the bash changes to take effect or run the following commands.

source ~/.bashrc
source ~/.bash_profile 

Tickets Resolved & Prep-Work Now Done?

Lets take a quick break and test what we have done thus far.

  1. Installed or requested Python2.6 or Python2.7
  2. Requested MySQLDB module 
  3. Edited .bashrc and .bash_profile with alias lines
  4. Logged out SSH then logged back in or ran source on the bash files 
source ~/.bash_profile
source ~/.bashrc

Now you should be able to execute "python" and see something similar:
username@host [~]# python
Python 2.6.2 (r262:71600, Aug  5 2009, 13:32:15)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-44)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>>


Verify your Python version and type Ctrl-D to exit the Python interpreter.

WARNING: From now on, I am going to be
using code that uses Python 2.6, so just be aware and change the Python version when changing directories
.

 

To install Python libraries you should use pip and the --prefix option.

pip install --prefix="/home/username/local/lib/$library_name/"

 

Installing Django

There are two typical ways of installing Django: Release or latest development version. Which to choose? I have always used the development version and have never had any problems. You could also download the latest release tarball too. If you do decide to use the tarball release, just keep in mind some of these steps are irrelevant and/or different.

Now Tiny accounts are only limited to 75Mb of space and performing a regular Subversion checkout takes just over 74Mb of space. Unacceptable. Seems like we are hosed, right? Luckily, we can export just the folder and set of files we need to get Django up and running. The rest of the checkout has a lot of bloat for keeping all the revision history, documentation, etc that is entirely unnecessary and can be found online where you can browse the source. This leaves the Django code at approximately 19Mb; definitely beats ~74Mb :D.

Ready? Great! So now lets install django into that site-packages directory we created earlier:

Django recently switched from svn to git so the installation has changed.
cd ~/local/lib/python2.x/site-packages
git clone git://github.com/django/django.git django-install
ln -s django-install/django django

This will export the core django-install code into the "site-package" directory then symlink the django directory above so the paths work correctly.

To test that you can use Django properly you should execute and see the following:

username@host [~/]# django-admin.py
Type 'django-admin.py help' for usage.

username@host [~/]# python
Python 2.6.2 (r262:71600, Aug  5 2009, 13:32:15)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-44)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
>>>

This is good, close out of the interpreter and Django is installed.

However, if something goes wrong:
username@host [~/]# django-admin.py
-jailshell: django-admin.py: command not found

# or

>>> import django
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named django
>>> 
or run 'python -c "import django"'

Check in .bash_profile that your PATH includes the where the django/bin directory is and that your PYTHONPATH includes the directory in which the ./django directory is located. If your .bash_profile appears correct, check the actual environment:
echo $PATH
echo $PYTHONPATH


If the paths don't appear on any of the echo outputs, make sure that you source'd the bash profile file or just logout and log back into your shell.

or if you get 

'ImportError: No module named importlib'

Then run 'pip install importlib' as root (or open support ticket and we can install it) then try running django-admin.py again as user.
 

Create a Django Project

Now, I won't go through all the steps of starting off your Django project, but I will do the bare minimum to get the basics up and running. Now I prefer to have a directory that holds my Django project, media folder, scripts, and templates:

cd ~/
mkdir website
cd website
# replace 'myproj' with whatever your project name
django-admin.py startproject myproj

# this is up to you, but it is nice to keep everything contained
mkdir media
mkdir scripts
mkdir templates

# we now have
# ~/website
#     ./media
#     ./mpyroj
#     ./scripts
#     ./templates


The last things that needs to get done is create a symlink to your project in the ./site-packages directory so Python know where to find your project. Remember: we added the ./site-packages to our PYTHONPATH so Python knows where to find everything; nice!
cd ~/local/lib/python2.6/site-packages
ln -s ~/website/myproj


Quick check that we can import our project in Python:
python
Python 2.6.2 (r262:71600, Aug  5 2009, 13:32:15)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-44)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import myproj
>>>
or run 'python -c "import myproj"'

No import errors? Great, lets move on!

Install Flup

Recall the link referencing how Django is preferred to be installed in the beginning? Well, using FCGI the "Django way" requires Flup to be installed. It may be a good idea to check the Flup website to see what the latest release is.
cd ~/
wget http://www.saddi.com/software/flup/dist/flup-1.0.2.tar.gz
tar xzvf flup-1.0.2.tar.gz
cd flup-1.0.2
cp -r flup ~/local/lib/python2.6/site-packages/


Quick check that we can import flup in Python:
python
Python 2.6.2 (r262:71600, Aug  5 2009, 13:32:15)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-44)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import flup
>>>
or run 'python -c "import flup"'

No import errors? Great, lets move on!

FCGI on Shared Hosting

We are almost at the end of our journey. First we need to create a simple FCGI program in our ~/public_html that will be executed that will dispatch web requests to your Django site. First create/open a file in your favorite editor "dispatch.fcgi" in your ~/public_html directory:
#!/usr/local/bin/python2.6

import sys
import os

# Make sure to change 'username' to your username!
sys.path.insert(0, '/home/username/local/lib/python2.6/site-packages')

os.environ['DJANGO_SETTINGS_MODULE'] = 'myproj.settings'

from django.core.servers.fastcgi import runfastcgi
runfastcgi(method="threaded", daemonize="false")

A few things to note. Replace the first line to where your python2.X is installed. You can check by executing `which python2.X` in case you aren't sure. Change the "username" to your login name. Finally, change "myproj.settings" to your "yourprojname.settings".

You can add additional FCGI settings to the runfastcgi call in the last line. One of the most useful for development is debug="true" which provides debug information before django's debugging machinery has loaded. You can see all settings in django.core.servers.fastcgi.

Also we need to make sure that this file is executable so that it can be run by Apache:
chmod 755 dispatch.fcgi


We can test the script by running:
./dispatch.fcgi

You should see HTML output the console! If so, we are in good shape.

If something goes wrong, make sure that FCGI is working by looking at the Testing FastCGI on this ASO wiki page for making sure FCGI is working on your shared hosting.

Modify .htaccess

In your ~/public_html directory, we just need to modify the .htaccess file so that web requests are dispatched to your dispatch.fcgi script.

Open up ~/public_html/.htaccess and the entire file should be:
AddHandler fcgid-script .fcgi
RewriteEngine On                              
RewriteCond %{REQUEST_FILENAME} !-f           
RewriteRule ^(.*)$ dispatch.fcgi/$1 [QSA,L]


Here is an explanation of what this is doing. The comments in the code below will cause an error, so use the one above.
AddHandler fcgid-script .fcgi               # use fast-script to execute our .fcgi file
RewriteEngine On                              # rewrite url request enabled
RewriteCond %{REQUEST_FILENAME} !-f           # if the FILENAME requested isn't an actual file, perform the next command
RewriteRule ^(.*)$ dispatch.fcgi/$1 [QSA,L]   # send requested urn to the dispatch.fcgi to be processed

Test your new Website

Go to http://www.yourwebsite.com!

Hopefully you should see the Django welcome page because you haven't created anything yet on your site. Enjoy!

When you make changes to your code and would like to see them on your site, just update the timestamp of your dispatch.fcgi file and Apache will restart your Django application for you.
touch mysite.fcgi


Admin Media


If you run into trouble with media not showing up in the admin side of your app (no css, images, etc), you may need to link to them from your site's document root:
  1. cd to your document root (i.e. ~/public_html)
  2. add a symlink to the django admin media:
$ ln -s /home/username/local/lib/python2.x/site-packages/django/contrib/admin/media media


More info from the official Django documentation here:

Conclusion

I hope this guide is helpful and that the ASO community may benefit from this wealth of information.

Notes

To make sure no one else on your shard hosting server can view your password in your project's [i]./settings.py[/i] file, we should change the permissions so only you can view and edit this file:
chmod 600 ~/website/myproj/settings.py
(24 vote(s))
This article was helpful
This article was not helpful

Help Desk Software by Kayako Fusion