Using virtualenv for Django projects

Nov 24, 2012

Today I am going to walk you through using virtualenv and virtualenvwrapper for deploying Django projects. The advantage of virtualenv is that it sets up your Python package dependencies separately for each virtualenv so that if you have multiple projects which need conflicting versions of the same package you will not have problems. It also makes it simpler to track dependencies. You can create a requirements file for use with Pip to install your dependencies for each project for example.

Installing

Install virtualenv, pip and virtualenvwrapper if not present. Depending on your system, you probably need to run these commands with sudo.

sudo easy_install virtualenv
sudo easy_install pip
sudo pip install virtualenvwrapper

Edit your .basrhc to add these lines (or .zshrc or equivalent for your shell of choice)

export WORKON_HOME=$HOME/.virtualenvs
# Edit this path to be wherever pip install virtualenvwrapper put your virtualenvwrapper.sh
source /usr/bin/virtualenvwrapper.sh
export PIP_VIRTUALENV_BASE=$WORKON_HOME
export PIP_RESPECT_VIRTUALENV=true

And also execute them in current shell or logout/back in or run them directly, or you can source them like this.

source ~/.bashrc

Now create a virtual env to work in:

mkvirtualenv --no-site-packages --distribute -p python2.6 my_test_env_name

You can choose with virtualenv to use with workon or just run workon to list your environments

workon some_env_name

You can remove a virtual env you no longer want like this:

rmvirtualenv env_to_kill

Original documentation by the author of virtualenvwrapper is available at http://www.doughellmann.com/articles/pythonmagazine/completely-different/2008-05-virtualenvwrapper/index.html

Install yolk which is a tool for querying what PyPI and Python packages are installed.

You can use it to detect what is installed in your Python environment.

pip install yolk
yolk -l # Lists all installed packages

You can install the requirements of an existing project from a file listing them like this.

pip install -r requirements.txt

For our purposes, we will of course need Django.

pip install Django

You can use the freeze option to pip create a requirements file matching what is currently installed in your virtualenv like this.

pip freeze > requirements.txt

Setting up your WSGI script

In order to get this working for Django using WSGI, you need your Django project’s .wsgi file setup correctly. Below is an example WSGI script, be sure to change the env_dir value.

import os
import sys
import site

# Find project directory by this file's path
proj_dir = os.path.dirname(__file__)
# specify environment dir
env_dir = "/home/ranton/.virtualenvs/my_test_env_name"

# Tell wsgi to add the Python site-packages to its path. 
site.addsitedir(os.path.join(env_dir,'lib/python2.6/site-packages'))

# add the project dir itself to the sys path
sys.path.append(proj_dir)

# add the egg cache
os.environ['PYTHON_EGG_CACHE'] = os.path.join(proj_dir,'.python-egg')

# define the settings module
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'

# Run the virtualenv activation script
activate_this = os.path.join(env_dir,"bin/activate_this.py")
execfile(activate_this, dict(__file__=activate_this))

import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

Configuring Apache

And of course you need to configure your Apache (or other web server) to load the project using WSGI.

You will need modwsgi installed for this to work. I do not cover modwsgi setup in depth here, but you can find more information in Django’s own documentation

# Be sure to change all the base paths to match where your Django project
# is actually installed on your server.
<VirtualHost \*:80>
     ServerAdmin webmaster@anvil@house.com
     ServerName www.mydomain.com

     DocumentRoot /var/www/mydemo/public_html

     <Directory /var/www/mydemo/app>
       Order allow,deny
       Allow from all
     </Directory>

     WSGIScriptAlias / /var/www/mydemo/app/django.wsgi
     # If your apache user is named something else you need to change it here.
     WSGIDaemonProcess  house.com user=apache  group=apache threads=5
     WSGIProcessGroup house.com

     Alias /static /var/www/html/static

     ErrorLog /var/www/mydemo/logs/error.log
     CustomLog /var/www/mydemo/logs/access.log combined
</VirtualHost>

Assuming everything is setup correctly you should be able to see your Django app running on your site. If things don’t work you will need to look at your server logs to see what is happening. Keep in mind that server setup like whether SELinux is in use can cause problems as well as the WSGI script and Apache configuration.

References