Saturday, February 12, 2011

How to install django on ubuntu using apache and mod_wsgi

Django is my favourite web framework, and one that I have become very familiar with over the last 3 years or so, as I develop web applications in it at work on an almost daily basis.

One of the unfortunate things about it though is that it is much more difficult to set up and deploy a web app written in Django than it is to deploy an app written in PHP, for example. Django and python aren't popular enough yet that you can easily find a cheap web host that supports them, so the next best option is to set up your own web server for hosting your applications.

A good way to do this is using Ubuntu server, Apache http server, mod_wsgi and MySQL database. Here are some basic instructions I wrote a while ago for setting up a production Django server with this combination:

How to setup django server with apache2 and MOD_WSGI

On a clean install of ubuntu

1. sudo apt-get install apache2

2. install mod_wsgi for apache2. (sudo apt-get install libapache2-mod-wsgi)

3. sudo apt-get install python

3. Download current stable version of django from www.djangoproject.com

4. uncompress the tar
tar xzvf Django-1.2.3.tar.gz
cd Django-1.2.3
sudo python setup.py install

4. create a new project in /usr/local/src/ (sudo django-admin.py startproject myproject)

5.
Add this to the apache2 httpd.conf file (/etc/apache2/httpd.conf):
Alias /media/ /var/www/media/
<Directory /var/www/media>
Order deny,allow
Allow from all
</Directory>
WSGIScriptAlias / /var/www/apache/django.wsgi
<Directory /var/www/apache>
Order deny,allow
Allow from all
</Directory>

6. create a new file in /var/www/apache/django.wsgi and put this in it:
import os, sys
root = os.path.join(os.path.dirname(__file__), '/usr/local/src')
sys.path.insert(0, root)
sys.path.append('/var/www')
sys.path.append('/usr/local/src/myproject')
os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

7. chmod o+r /var/www/apache/django.wsgi

8. chmod o+rx /var/www/apache

9. chmod o+rx /usr/local/src

10. Put this line at the end of /etc/profile and /etc/bash.bashrc
export PYTHONPATH=/usr/local/src/myproject:$PYTHONPATH
export PYTHONPATH=/usr/local/src:$PYTHONPATH

7. Restart apache
sudo /etc/init.d/apache2 restart


To install mysql db and link it with django
1. sudo apt-get install mysql-server

2. install python-mysqldb (sudo apt-get install python-mysqldb)

3. log in to mysql and create a database for project
mysql -u root -p
CREATE DATABASE myproject;
GRANT ALL ON myproject.* TO root@localhost;

4. edit myproject/settings.py and input database settings

5. cd to project directory then ./manage.py syncdb


To get admin site working
1. # Add 'django.contrib.admin'  to your INSTALLED_APPS setting.

2. # Admin has two dependencies - django.contrib.auth and django.contrib.contenttypes. If these applications are not in your INSTALLED_APPS list, add them.

3. sudo chmod o+r django.wsgi

4. sudo chmod o+rx /var/www/apache

5. copy admin media files to /var/www/media/
   The files can be found in /usr/local/lib/python2.6/dist-packages/django/contrib/admin/media
   sudo cp /usr/local/lib/python2.6/dist-packages/django/contrib/admin/media/* /var/www/media/ -a

6. cd to project directory then ./manage.py syncdb
  

Notes:
To check django version:
python
import django
print django.VERSION

To tail apache log:
tail -f /var/log/apache2/error.log

12 comments:

  1. I'd be very interested in hearing from people on whether the steps above worked for them, and any improvements you suggest.

    ReplyDelete
  2. Step 1. Which apache? Event, prefork, worker?

    Step 4. Better way is to use virtualenv for isolation and pip for installing pacakges (and Django too).

    ReplyDelete
  3. When using virtual env with mod_wsgi make sure the virtual env python is used and the virtual env site-packages are first on th python path

    #django.wsgi
    import os, sys, site

    #Calculate the path based on the location of the WSGI script.
    APACHE_WSGI = os.path.abspath(__file__)
    APACHE_DIR = os.path.dirname(APACHE_WSGI)
    PROJECT_ROOT = os.path.dirname(APACHE_DIR)
    VIRTUAL_ENV = os.path.dirname(PROJECT_ROOT)
    sys.path.append(PROJECT_ROOT)

    # DON'T USE activate virtualenv
    # activate_this = os.path.join(VIRTUAL_ENV,'bin/activate_this.py')
    # execfile(activate_this, dict(__file__=activate_this))

    # apply project to python path
    SITE_PACKAGES=os.path.join(VIRTUAL_ENV,'lib/python2.6/site-packages')
    ALLDIRS = [ SITE_PACKAGES, PROJECT_ROOT, VIRTUAL_ENV]
    # Remember original sys.path.
    prev_sys_path = list(sys.path)

    # Add each new site-packages directory.
    for directory in ALLDIRS:
    site.addsitedir(directory)

    # Reorder sys.path so new directories at the front.
    new_sys_path = []
    for item in list(sys.path):
    if item not in prev_sys_path:
    new_sys_path.append(item)
    sys.path.remove(item)

    sys.path[:0] = new_sys_path

    # run Django
    import django.core.handlers.wsgi
    os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
    application = django.core.handlers.wsgi.WSGIHandler()

    ReplyDelete
  4. I use buildout to limit the amount of stuff I need to install manually and/or globally.

    Buildout has a "djangorecipe" extension that takes care of downloading django and creating a proper wsgi script for you, all ready for plugging into mod_wsgi.

    In addition, I generate my apache config file from within buildout, too, to get all the paths right. Including a project-local apache log file.

    See http://reinout.vanrees.org/weblog/2011/01/12/django2.html (search for "wsgi" on that page).

    ReplyDelete
  5. What is the "hunterparty" in 10. PYTHONPATH=/usr/local/src/hunterparty:$PYTHONPATH.

    ReplyDelete
  6. You have NO IDEA how much i appreciate this.

    ReplyDelete
  7. Great beginner's tutorial! Thanks for sharing!

    ReplyDelete
  8. Hi, great tutorial so far but I have faltered at step 5 of the last section! I am running python 2.7 on Ubuntu 11.10 with MYSQL. I installed Django 1.4 via pip. I am not able to copy the said media files across to var/www/media as my python2.7 dist-packages/django/contrib/admin/ directory does not contain a 'media' directory or files. What do you recommend?

    Thanks in advance
    Jim

    ReplyDelete
    Replies
    1. UPDATE: Media files appear to have been moved in version 1.4 of Django as per Django Projects extract below:

      If you're implicitly relying on the path of the admin static files within Django's source code, you'll need to update that path. The files were moved from django/contrib/admin/media/ to django/contrib/admin/static/admin/.

      Hopefully now I am good to go. Thanks Simon for such an easy to follow tutorial!

      Jim

      Delete
  9. And what about deploying django app if i use it as a package (i use setup.py to create a package that i want to deploy)
    how to configure prod server?

    Any one has an idea?
    thank you in advance

    ReplyDelete
  10. I just tried this and instead of 'httpd.conf', I had to use 'apache2.conf'. I didn't look too far into it, but I'm guessing it's because of a different apache2 version?

    ReplyDelete