Working with Virtualenv on Django Projects

If you have used Django extensively, you must be aware that perhaps one of the biggest issues with this popular framework is that a project created in one Django version is not compatible with a different one. This means that if a project was started with Django 1.4.x and you upgrade your package to Django 1.5.x, your project would refuse to run.

A simple and very obvious solution to this problem is to stick with a single version of Django for all your projects. Agreed you can control your own projects, but what about projects started by others? How then do you contribute to multiple repositories, each built in a different version of Django?

There is a hack to do that. You can keep the tarballs of different Django versions on your local machine and install different the proper version prior to running a project. However, this process is highly inefficient. What else could you do?

In fact, this problem is not just related to Django. There are many case when a certain version of a package doesn’t have backward or forward compatibility. Take for example, BeautifulSoup, a python library for parsing HTML and XML documents. BeautifulSoup 4 released with drastic changes and hence, scripts utilizing old versions aren’t compatible with BeautifulSoup 4.

Virtualenv:

Virtualization comes to the rescue. The basic plan is to create isolated environments, each running their own versions of packages, not just limited to Django.

Virtualenv is the tool in Python which helps in creating new virtual environments for your projects, with their own install directories, isolated from the system directories. The interesting thing to note is that you can create virtual environments with various python versions, with each virtual environment having its own set of packages.

Installing Virtualenv and setting it up for your project:

Working with Django and Virtualenv is easy when you have pip installed. Pip is a tool for managing python packages (an alternative is easy_install). You would basically use pip to install your packages. In some systems, it is required to have python-dev installed so that you can run virtualenv flawlessly. It is also advisable to upgrade to the latest version of pip. In many Linux systems like Ubutnu, you can install the two using the following commands.

sudo apt-get install python-pip python-dev
sudo pip install –upgrade pip

 

In other systems, you can follow the official documentation of pip to help in the installation of the same.

Please note that virtualenv documentation advise against using easy_install to install virtualenv when using setuptools < 0.9.7. The reason is that easy_install didn’t download from PyPI over SSL and was broken in some subtle ways.

This post assumes that your project has a requirements.txt file. In general, the requirements.txt file is present at the root of the python repository (or the src folder) and contains all the packages and their corresponding versions that are required to run the project. A good example of a requirements.txt file is that of e-cidadania, an e-democracy portal.

PIL
python-dateutil==1.5
django-guardian==1.1.0.beta
south
djangorestframework
markdown
django-filter
pyyaml
defusedxml
django-oauth-plus
django-oauth2-provider

You can generate your project’s requirements by running the pip freeze command that lists all packages that are installed in your local machine with their versions.

pip freeze > requirements.txt

Do note that this process can lead to certain unnecessary packages being written to the requirements file which are installed in your local machine but not required for the project. You must manually edit the requirements file in that case.

You can create a virtual environment by running the simple command,

virtualenv <environment_name>

Two important things to note here are that this command creates two directories.

<environment_name>/lib/pythonX.X/site-packages – All python libraries that you install will go here.
<environment_name>/bin/python/ – This is the location of the python interpreter for your virtual environment.

You can either add the option of –no-site-packages or –system-site-packages with your previous commands to specify whether or not you want to inherit all the packages installed in your system.

You need to activate your virtual environment by running-

source ./<environment_name>/bin/activate

You should see (<environment_name>) $ at your command prompt, letting you know that you’re running the proper virtualenv install. To deactivate, you can just run the following to come out of the environment.

deactivate

You need to move your project’s directory inside the virtualenv directory and install the dependencies by running-

pip install requirements.txt

You may or may not want to add sudo depending on whether your user has the permissions to install dependencies or not. Database migrations can be done effectively through the package South.

Using mod_wsgi and Apache to deploy:

The module of the Apache web server that lets us host any web application written in Python is mod_wsgi. It involves making a .wsgi file that would deploy our project. In Ubuntu, you install it using the following command-

sudo apt-get install libapache2-mod-wsgi

Open up a text editor and create the following file- /etc/apache2/sites-available/<my_app>

(Courtesy- The Code Ship)

<VirtualHost *:80>
ServerAdmin contact@localhost
ServerName my_app
ServerAlias /my_app/
WSGIScriptAlias /var/www/my_app/index.wsgi
Alias /static/ /var/www/mydomain.com/static/
<Location “/static/”>
Options -Indexes
</Location >
</VirtualHost >

Note that it is imperative that you add a line for rendering the static files. These static files are generated from the collectstatic command in manage.py. You can add one for the media files too, if it is hosted on the same server.

Next, you need to open up your text editor and create the following file- /var/www/mydomain.com/index.wsgi

import os
import sys
import site
# Add the site-packages of the chosen virtualenv to work with
site.addsitedir(‘~/.virtualenvs/<environment_name>/local/lib/python2.7/site-packages’)
# Add the app’s directory to the PYTHONPATH
sys.path.append(‘/home/django_projects/MyProject’)
sys.path.append(‘/home/django_projects/MyProject/myproject’)
#to set enviroment settings for Django apps
os.environ[‘DJANGO_SETTINGS_MODULE’] = ‘myproject.settings’
# Activate your virtual env
activate_env=os.path.expanduser(“~/.virtualenvs/myprojectenv/bin/activate_this.py”)
execfile(activate_env, dict(__file__=activate_env))
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

Finally, do not forget to restart apache!

sudo service apache2 restart

Alternately, you can deploy your application without using virtualenv, by referring to the tutorial on the Django documentation.

Let’s hope that these steps helped you understand the working on Virtualenv and why it is getting so much popularity!