development with virtualenv

Posted on February 26, 2010

You should have installed virtualenv, pip, and virtualenvwrapper by now.

Boostrapping project

This section is not unique to Django projects. Any Python project can use a virtualenv like this. Creating a virtualenv is easy:

mkvirtualenv PROJECTNAME

Note this will not create a project directory. You need to do this yourself:

mkdir -p PROJECTDIR

Very often, you will like to modify PYTHONPATH to include your project directory in it. This depends on layout of your project of course. More on this later.

add2virtualenv $(pwd)/PROJECTDIR

Deactivating virtualenv

To deactivate or log out of a virtualenv, simply type:

deactivate

Or switch to another project:

workon ANOTHERPROJECT

Installing dependencies

Once you have activated your virtualenv by mkvirtualenv above or manually by

workon PROJECT

you can start installing dependencies with pip. Let's install the Django trunk with the now very popular South:

pip install -e svn+http://code.djangoproject.com/svn/django/trunk#egg=django
pip install -e hg+http://bitbucket.org/andrewgodwin/south#egg=south

Make sure you check out the pip documentation for more. You may still want to and can install packages globally and the virtualenv will recognize it. The following will install PIL for example:

apt-get install python-imaging

Django project layout

Much has been written on project layout in Django projects and many exist. Here is one of them.

mysite/
    docs/
    resources/
    myproject/
    setup.py
    INSTALL
    AUTHORS
    README

mysite is the top level project directory and can be the name of the virtualenv for clarity. It contains the django project myproject and other files and directories which do not have anything to do with Django. This extra directory (atop myproject) has been recommended by many and trust me, you will need it later as your project grows.

myproject/
    settings.py
    urls.py
    apps/
        myapp1/
        myapp2/
    libs/
    templates/
        myapp1/
        myapp2/

You will see why we are having this discussion in the virtualenv article at all.

Referencing other modules

There is little confusion about how to refer to Django applications and Django parts of the code. Most projects do it like this:

from django.contrib.auth.models import User
from django.contrib.contenttypes import generic
from django.db import connection

Given the layout above we can refer to myprojects's objects in the same fashion:

from myproject.apps.myapp1.models import Model1
from myproject.libs.mylib import myfunc

You can clearly separate objects from either one. Of course, this means PYTHONPATH contains the path to mysite like you should have added earlier:

add2virtualenv $(pwd)/mysite

DJANGO_SETTINGS_MODULE

With the layout from above, DJANGO_SETTINGS_MODULE has to be mysite.settings. You can have virtualenvwrapper set it for you each time you switch to your virtualenv:

cdvirtualenv
echo "export DJANGO_SETTINGS_MODULE=mysite.settings" >bin/postactivate