Call us on +44 (0) 1273 621110

A Generic wsgi file for deploying Django with virtualenv and mod_wsgi

Virtualenv is one of several tools that all good Python developers should know. It lets you run several Python applications side-by-side, each with their own Python libraries installed. That’s a godsend when you have several projects running on the same server, that update at different rates. It also means you know you are free to upgrade the libraries for one project, without having to worry about backwards incompatible changes breaking otherwise unrelated projects. In short it helps keep you sane!

Since mod_python has become inactive, mod_wsgi is the preferred way to get a Django site running under Apache. With mod_wsgi you have a .wsgi file to run the app. It’s just regular Python, with a different file extension. This means it’s easy to use virtualenv with a Django site running with mod_wsgi.

I tend to create a virtualenv inside the main folder of my projects:


    $ cd my-django-project
    $ virtualenv --no-site-packages .

This creates the folders bin, lib (as well as a few others).

Starting with the notes on Virtual Environments on the mod_wsgi wiki, my generic .wsgi file searches in the lib folder for the virtualenv’s site-packages and adds it to the Python path. In this way no hard-coded/absolute paths are needed. As long as the virtualenv is setup in the same manor this .wsgi should work:


import os
import site
import sys

# Remember original sys.path.
prev_sys_path = list(sys.path) 

# we add currently directory to path and change to it
pwd = os.path.dirname(os.path.abspath(__file__))
os.chdir(pwd)
sys.path = [pwd] + sys.path

# find the site-packages within the local virtualenv
for python_dir in os.listdir('lib'):
    site_packages_dir = os.path.join('lib', python_dir, 'site-packages')
    if os.path.exists(site_packages_dir):
        site.addsitedir(os.path.abspath(site_packages_dir))

# 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

# now start django
from django.core.handlers.wsgi import WSGIHandler
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
application = WSGIHandler()

This also means you can use the same file for a staging environment or a local Apache dev server. Anyway thought it was something useful to share.

2 Comments
  1. Oh, this is quite nice… I’ve been doing some stuff using the pinax one, this lives in ‘deploy’, with the machines virtualenv being at ../${hostname}-env

    I’ll probably give this one a go as it looks pretty nice.

    For the moment setting up apache etc is scripted with judicious use of sed etc, looking forward to moving to fabric in the near future though :)

  2. Indeed it’s something useful to share! Thanks!

Address

Vantage Point
Brighton, East Sussex
United Kingdom
BN1 4GW
Telephone: +44 (0) 1273 621110

Latest Posts