Step-by-step instructions for installing Django 1.2.7 on Ubuntu 10.04 LTS (Lucid Lynx).
python -V: Python 2.6.5sudo apt-get install
python-devsudo apt-get install
python-setuptoolsopenssl version: OpenSSL 0.9.8k 25 Mar
2009.sudo
apt-get install libssl-devgcc --version: gcc version 4.4.3 (Ubuntu
4.4.3-4ubuntu5)make -v: GNU Make 3.81sudo apt-get
install mysql-server-5.1sudo apt-get
install libmysqlclient-devStore the downloaded files and source code in the
~/src/ directory:
mkdir ~/src && cd ~/src/
wget http://nginx.org/download/nginx-0.7.65.tar.gz
&& tar -zxvf nginx-0.7.65.tar.gz
wget
http://github.com/downloads/libevent/libevent/libevent-2.0.16-stable.tar.gz
&& tar -zxvf
libevent-2.0.16-stable.tar.gz
wget
http://pypi.python.org/packages/source/g/greenlet/greenlet-0.3.1.tar.gz
&& tar -zxvf greenlet-0.3.1.tar.gz
wget
http://pypi.python.org/packages/source/g/gevent/gevent-0.13.6.tar.gz
&& tar -zxvf gevent-0.13.6.tar.gz
wget
http://ignum.dl.sourceforge.net/project/mysql-python/mysql-python/1.2.3/MySQL-python-1.2.3.tar.gz
&& tar -zxvf MySQL-python-1.2.3.tar.gz
wget
http://github.com/downloads/petehunt/PyMySQL/PyMySQL-0.5.tar.gz
&& tar -zxvf PyMySQL-0.5.tar.gz
wget -O Django-1.2.7.tar.gz
http://www.djangoproject.com/download/1.2.7/tarball/
&& tar -zxvf Django-1.2.7.tar.gz
Minimal configuration for using Nginx as a reverse proxy and for serving static files:
cd ~/src/nginx-0.7.65/
./configure --without-http_access_module --without-http_auth_basic_module --without-http_autoindex_module --without-http_browser_module --without-http_empty_gif_module --without-http_fastcgi_module --without-http_geo_module --without-http_limit_req_module --without-http_limit_zone_module --without-http_map_module --without-http_memcached_module --without-http_referer_module --without-http_rewrite_module --without-http_ssi_module --without-http_userid_module --with-http_ssl_module
sudo make && sudo make install
Create the Nginx init file
/etc/init.d/nginx:
#! /bin/sh
### BEGIN INIT INFO
# Provides: nginx
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts the nginx web server
# Description: starts nginx using start-stop-daemon
### END INIT INFO
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/nginx/sbin:/usr/local/nginx
DAEMON=/usr/local/nginx/sbin/nginx
NAME=nginx
DESC=nginx
test -x $DAEMON || exit 0
# Include nginx defaults if available
if [ -f /etc/default/nginx ] ; then
. /etc/default/nginx
fi
set -e
case "$1" in
start)
echo -n "Starting $DESC: "
start-stop-daemon --start --quiet --pidfile /usr/local/nginx/logs/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS
echo "$NAME."
;;
stop)
echo -n "Stopping $DESC: "
start-stop-daemon --stop --quiet --pidfile /usr/local/nginx/logs/$NAME.pid
echo "$NAME."
;;
restart|force-reload)
echo -n "Restarting $DESC: "
start-stop-daemon --stop --quiet --pidfile /usr/local/nginx/logs/$NAME.pid
sleep 1
start-stop-daemon --start --quiet --pidfile /usr/local/nginx/log/$NAME.pid --exec $DAEMON -- $DAEMON_OPTS
echo "$NAME."
;;
*)
N=/etc/init.d/$NAME
echo "Usage: $N {start|stop|restart|force-reload}" >&2
exit 1
;;
esac
exit 0
Make the file executable and add it to the default run levels:
sudo chmod +x /etc/init.d/nginx
sudo /usr/sbin/update-rc.d -f nginx defaults
Edit the Nginx configuration file
/usr/local/nginx/conf/nginx.conf to configure
Nginx as a reverse proxy. The Django WSGI server will be
listening on localhost at port 8000.
Nginx is configured to handle HTTP status codes of 400 and
higher if a matching error_page directive exists.
Also, any request for /static/*,
/robots.txt and /favicon.ico is
served statically from /usr/local/nginx/html:
location /static/ {
root html;
}
location /robots.txt {
root html;
}
location /favicon.ico {
root html;
}
location / {
proxy_pass http://localhost:8000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_intercept_errors on;
}
Libevent is required for compiling Gevent:
cd ~/src/libevent-2.0.16-stable/
./configure
sudo make && sudo make install
Register Libevent, add the following path to the
/etc/ld.so.conf.d/libevent-i386.conf file:
/usr/local/lib
And run:
sudo ldconfig
Greenlet is used by Gevent as an alternative to Python’s built in coroutines:
cd ~/src/greenlet-0.3.1/
sudo python setup.py build && sudo python setup.py install
Gevent provides an high-performance WSGI web server and a simple way for monkeypatching the stdlib to make some parts of it cooperative with greenlets:
cd ~/src/gevent-0.13.6/
sudo python setup.py build && sudo python setup.py install
MySQLdb is required for executing python manage.py
syncdb from the command line:
cd ~/src/MySQL-python-1.2.3/
sudo python setup.py build && sudo python setup.py install
PyMySQL is a pure Python MySQL client and a drop-in replacement for MySQLdb. Being pure Python, PyMySQL can take full advantage of the monkey patched standard library:
cd ~/src/PyMySQL-0.5/
sudo python setup.py build && sudo python setup.py install
Build and install Django using setup.py:
cd ~/src/Django-1.2.7/
sudo python setup.py build && sudo python setup.py install
Copy the Django admin static files to
/usr/local/nginx/html/static/:
sudo mkdir /usr/local/nginx/html/static
sudo cp -rv ~/src/Django-1.2.7/django/contrib/admin/media/* /usr/local/nginx/html/static/
Typing the following commands at the python
command prompt (replacing password
with the actual password):
import MySQLdb
conn = MySQLdb.connect(host='localhost', user='root', passwd='password', db='mysql')
cursor = conn.cursor()
cursor.execute('SELECT VERSION();')
row = cursor.fetchone()
server_version = row[0]
cursor.close()
conn.close()
print 'server version:', server_version
should produce:
server version: 5.1.41-3ubuntu12.10
Typing the following commands at the python
command prompt (replacing password
with the actual password):
import pymysql
pymysql.install_as_MySQLdb()
# same as above
import MySQLdb
conn = MySQLdb.connect(host='localhost', user='root', passwd='password', db='mysql')
cursor = conn.cursor()
cursor.execute('SELECT VERSION();')
row = cursor.fetchone()
server_version = row[0]
cursor.close()
conn.close()
print 'server version:', server_version
should produce:
server version: 5.1.41-3ubuntu12.10
Typing the following commands at the python
command prompt:
import django
print 'django version:', django.get_version()
should produce:
django version: 1.2.7
Start the Nginx server:
sudo /etc/init.d/nginx start
Enter the following commands at the python
command prompt:
from gevent import wsgi
def hello_world(environ, start_response):
start_response('200 OK', [])
return ['<html>Hello, world!</html>']
wsgi.WSGIServer(('', 8000), hello_world, spawn=None).serve_forever()
Running:
wget -qO- --server-response http://localhost/
should produce:
HTTP/1.1 200 OK
Server: nginx/0.7.65
Date: Fri, 23 Oct 2009 09:05:19 GMT
Content-Type: text/html; charset=ISO-8859-1
Connection: keep-alive
Content-Length: 26
<html>Hello, world!</html>
The Django project must be accessible from within the
/usr/local/wsgi/ directory:
sudo mkdir /usr/local/wsgi
Create the /usr/local/wsgi/django-bootstrap.py
file:
#!/usr/bin/env python
#
# Copyright: ©2011 Gabriele Pierfederici
# http://www.gabrielepierfederici.com/archive/setting-up-django-on-ubuntu.html
#
import sys, os, traceback
from optparse import OptionParser
from django.core.signals import got_request_exception
import django.core.handlers.wsgi
from gevent import monkey
from gevent.wsgi import WSGIServer
import pymysql
def exception_printer(sender, **kwargs):
traceback.print_exc()
def django_app(settings):
os.environ['DJANGO_SETTINGS_MODULE'] = settings
got_request_exception.connect(exception_printer)
return django.core.handlers.wsgi.WSGIHandler()
def wsgi_server(host, port, application):
return WSGIServer((host, port), application, log=False)
if __name__ == '__main__':
path = os.path.abspath(os.path.dirname(__file__))
if path not in sys.path:
sys.path.append(path)
parser = OptionParser("usage: %prog [options] arg")
parser.add_option('--host', type='string', default='localhost', dest='host', help="host name or IP address [default: %default]")
parser.add_option('--port', type='int', default=8000, dest='port', help="tcp port [default: %default]")
parser.add_option('--settings', type='string', dest='settings', help="django settings module (mandatory)")
options = parser.parse_args()[0]
if not options.settings:
print "mandatory option --settings is missing\n"
parser.print_help()
exit(-1)
parser.destroy()
monkey.patch_all()
pymysql.install_as_MySQLdb()
server = wsgi_server(options.host, options.port, django_app(options.settings))
try:
server.serve_forever()
except KeyboardInterrupt:
pass
Make the file executable:
sudo chmod +x /usr/local/wsgi/django-bootstrap.py
Create the django user and home directory, the
project will then be created in the ~/projects/
directory:
sudo useradd -d /home/django -m django && sudo su django
mkdir ~/projects && cd ~/projects/
django-admin.py startproject mysite
exit
Create a symbolic link to
/home/django/projects/mysite in
/usr/local/wsgi/:
sudo ln -s /home/django/projects/mysite/ /usr/local/wsgi/mysite
Create the init script file /etc/init.d/mysite
to start and stop the WSGI server for mysite
automatically:
#! /bin/sh
### BEGIN INIT INFO
# Provides: mysite application instance
# Required-Start: $all
# Required-Stop: $all
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts instance of mysite app
# Description: starts instance of mysite app using start-stop-daemon
### END INIT INFO
############### EDIT ME ##################
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/wsgi
DAEMON=/usr/local/wsgi/django-bootstrap.py
USER=django
# Uncomment to enable custom settings for each individual environment (development, staging, production)
# ENV=production
# django project name
NAME=mysite
DESC=mysite
# django settings module
DJANGO_SETTINGS_MODULE=$NAME.settings
if [ -n "$ENV" ] ; then
DJANGO_SETTINGS_MODULE="$DJANGO_SETTINGS_MODULE.$ENV"
fi
# startup args
DAEMON_OPTS=" --host localhost --port 8000 --settings $DJANGO_SETTINGS_MODULE"
PID_FILE=/var/run/$NAME.pid
############### END EDIT ME ##################
test -x $DAEMON || exit 0
set -e
case "$1" in
start)
echo -n "Starting $DESC: "
start-stop-daemon -c $USER --start --quiet --background --pidfile $PID_FILE --make-pidfile --exec $DAEMON -- $DAEMON_OPTS
echo "$NAME."
;;
stop)
echo -n "Stopping $DESC: "
start-stop-daemon -c $USER --stop --quiet --pidfile $PID_FILE
echo "$NAME."
;;
restart|force-reload)
echo -n "Restarting $DESC: "
start-stop-daemon -c $USER --stop --quiet --pidfile $PID_FILE
sleep 1
start-stop-daemon -c $USER --start --quiet --background --pidfile $PID_FILE --make-pidfile --exec $DAEMON -- $DAEMON_OPTS
echo "$NAME."
;;
*)
N=/etc/init.d/$NAME
echo "Usage: $N {start|stop|restart|force-reload}" >&2
exit 1
;;
esac
exit 0
Make the file executable and add it to the default run levels:
sudo chmod +x /etc/init.d/mysite
sudo /usr/sbin/update-rc.d -f mysite defaults
Create the database and the database user for the project
(replace password with the actual
password):
mysql -u root -p
CREATE DATABASE mysite CHARACTER SET utf8;
GRANT ALL ON mysite.* TO `mysite`@`localhost` IDENTIFIED BY 'password';
FLUSH PRIVILEGES;
quit
Edit the DATABASES section in
/usr/local/wsgi/mysite/settings.py
(replace password with the actual
password)::
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'mysite',
'USER': 'mysite',
'PASSWORD': 'password',
'HOST': '',
'PORT': '',
'default-character-set': 'utf8',
'OPTIONS' : {
'init_command': 'SET storage_engine=INNODB',
}
}
}
Edit /usr/local/wsgi/mysite/settings.py replace
the ADMIN_MEDIA_PREFIX and
INSTALLED_APPS sections with:
ADMIN_MEDIA_PREFIX = '/static/'
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
# Uncomment the next line to enable the admin:
'django.contrib.admin',
# Uncomment the next line to enable admin documentation:
# 'django.contrib.admindocs',
)
Edit /usr/local/wsgi/mysite/urls.py:
from django.conf.urls.defaults import *
# Uncomment the next two lines to enable the admin:
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
# Example:
# (r'^mysite/', include('mysite.foo.urls')),
# Uncomment the admin/doc line below to enable admin documentation:
# (r'^admin/doc/', include('django.contrib.admindocs.urls')),
# Uncomment the next line to enable the admin:
(r'^admin/', include(admin.site.urls)),
)
Running python manage.py syncdb should prompt
the creation of the superuser:
sudo su django
cd ~/projects/mysite/
python manage.py syncdb
exit
sudo /etc/init.d/mysite start
Copyright: ©2011 Gabriele Pierfederici. All rights reserved. Reproduction or redistribution of content prohibited without permission of the author.