|
This is just a brief write-up on the steps that I took to get a basic Django application up and runnning with an On-Rev hosting account. To avoid having to embed a bunch of hyperlinks in the main text, I've include a complete references section at the bottom of the post. I'm going to assume that you have contacted On-Rev support and gotten them to grant you SSH access to your account. That is necessary to complete the following steps.
As far as I know, On-Rev does not currently support mod-python or FastCGI, so we are limited for now to using plain CGI. This is not very efficient but I think as the On-Rev service matures they will probably offer other options.
Tweak the Environment
We will be installing some packages and since we don't have root access everything will be installed relative to our $HOME directory. Note that when you see the "#" character in the code examples, this is NOT a root prompt. It is the default jailshell prompt.
# mkdir -p ~/usr/bin
# mkdir -p ~/usr/lib/python2.4/site-packages
Edit your ~/.bash_profile as follows, then log out and back in again for the changes to take effect.
export PATH=$PATH:$HOME/bin:$HOME/usr/bin
export PYTHONPATH=$HOME/usr/lib/python2.4/site-packages
Install Mercurial
I needed the Mercurial distributed source code management system to check-out some code (see further down). Plus it is my personal favorite source-code control system.
# mkdir ~/projects
# cd ~/projects
# wget http://www.selenic.com/mercurial-stable-snapshot.tar.gz
# tar xfz mercurial-stable-snapshot.tar.gz
# rm mercurial-stable-snapshot.tar.gz
# cd mercurial-ea82a23cf887/
# python setup.py install --root $HOME
Install SQLite
For my test Django project I wanted to use the SQLite database. Since we only have python version 2.4.3 available to us right now, we have to install the SQLite libraries and Python interface.
# cd ~/projects
# wget http://www.sqlite.org/sqlite-amalgamation-3.6.13.tar.gz
# tar xfz sqlite-amalgamation-3.6.13.tar.gz
# rm sqlite-amalgamation-3.6.13.tar.gz
# cd sqlite-3.6.13
# ./configure --prefix=$HOME
# make
# make install
# cd ~/projects
# hg clone http://oss.itsystementwicklung.de/hg/pysqlite/
# cd pysqlite
You need to tweak a few things in the setup.cfg file. Replace 'HOME' with the name of your home directory.
include_dirs=/home/HOME/include
library_dirs=/home/HOME/lib
Now we can build/install the Python SQLite interface.
# python setup.py install --root=$HOME
Install Django
I'm going to install Django by creating a symbolic link in a directory on the PYTHONPATH directly to the django module rather than performing a standard Django installation. This makes it very easy to upgrade Django by simply cd'ing to the ~/projects/django-trunk/ directory and issuing the svn up command.
# cd ~/projects
# svn co http://code.djangoproject.com/svn/django/trunk django-trunk
# cd ~/usr/lib/python2.4/site-packages/
# ln -s ~/projects/django-trunk/django
# cd ~/bin
# ln -s ln ~/projects/django-trunk/django/bin/django-admin.py
Create a small Django test application
# cd ~/projects
# django-admin.py startproject djtest
I'm going to assume that, at this point, you know how to configure your Django project, create one or more apps, fill in some models, views, and urls, and populate your database. Let's now look at the CGI hookup.
# cd ~/public_html/cgi-bin
Create/edit a file called django.cgi in the cgi-bin directory. Look for the TODO comments for places that you have to customize it for your installation. I got this script from the seamusc.com blog post that is listed in the references below.
#!/usr/bin/python
"""
django.cgi
A simple cgi script which uses the django WSGI to serve requests.
Code copy/pasted from PEP-0333 and then tweaked to serve django.
http://www.python.org/dev/peps/pep-0333/#the-server-gateway-side
This script assumes django is on your sys.path, and that your site code is at
/home/mycode/mysite. Copy this script into your cgi-bin directory (or do
whatever you need to to make a cgi script executable on your system), and then
update the paths at the bottom of this file to suit your site.
This is probably the slowest way to serve django pages, as the python
interpreter, the django code-base and your site code has to be loaded every
time a request is served. FCGI and mod_python solve this problem, use them if
you can.
In order to speed things up it may be worth experimenting with running
uncompressed zips on the sys.path for django and the site code, as this can be
(theorectically) faster. See PEP-0273 (specifically Benchmarks).
http://www.python.org/dev/peps/pep-0273/
Make sure all python files are compiled in your code base. See
http://docs.python.org/lib/module-compileall.html
"""
import os, sys
# insert a sys.path.append("whatever") in here if django is not
# on your sys.path.
# Add a custom Python path.
# TODO - Replace 'USER' with the name of your $HOME directory
# TODO - replace 'PROJECT' with the name of your Django project
sys.path.append("/home/USER/usr/lib/python2.4/site-packages")
sys.path.append("/home/USER/projects")
sys.path.append("/home/USER/projects/PROJECT")
import django.core.handlers.wsgi
def run_with_cgi(application):
environ = dict(os.environ.items())
environ['wsgi.input'] = sys.stdin
environ['wsgi.errors'] = sys.stderr
environ['wsgi.version'] = (1,0)
environ['wsgi.multithread'] = False
environ['wsgi.multiprocess'] = True
environ['wsgi.run_once'] = True
if environ.get('HTTPS','off') in ('on','1'):
environ['wsgi.url_scheme'] = 'https'
else:
environ['wsgi.url_scheme'] = 'http'
headers_set = []
headers_sent = []
def write(data):
if not headers_set:
raise AssertionError("write() before start_response()")
elif not headers_sent:
# Before the first output, send the stored headers
status, response_headers = headers_sent[:] = headers_set
sys.stdout.write('Status: %s\r\n' % status)
for header in response_headers:
sys.stdout.write('%s: %s\r\n' % header)
sys.stdout.write('\r\n')
sys.stdout.write(data)
sys.stdout.flush()
def start_response(status,response_headers,exc_info=None):
if exc_info:
try:
if headers_sent:
# Re-raise original exception if headers sent
raise exc_info[0], exc_info[1], exc_info[2]
finally:
exc_info = None # avoid dangling circular ref
elif headers_set:
raise AssertionError("Headers already set!")
headers_set[:] = [status,response_headers]
return write
result = application(environ, start_response)
try:
for data in result:
if data: # don't send headers until body appears
write(data)
if not headers_sent:
write('') # send headers now if body was empty
finally:
if hasattr(result,'close'):
result.close()
# Change this to the directory above your site code.
# TODO - Replace 'USER' with the name of your $HOME directory
# TODO - replace 'PROJECT' with the name of your Django project
os.chdir("/home/USER/projects/PROJECT")
# Change mysite to the name of your site package
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
run_with_cgi(django.core.handlers.wsgi.WSGIHandler())
Be sure and make your django.cgi script executable:
# chmod a+x django.cgi
That's pretty much it. Let's assume that your On-Rev domain is test.on-rev.com and you want to access the admin interface of your Django application. Then the URL would be this:
http://teset.on-rev.com/cgi-bin/django.cgi/admin/
References
|