Desplegar Django bajo Apache con WSGI en un virtualenv, *y que funcione*

El despliegue de Django es una de las pocas cosas claramente mejorables de este estupendo framework. Suele dar más de un dolor de cabeza porque es un poco lío establecer correctamente las variables de entorno. Un caso concreto que me ha dado bastantes problemas es desplegarlo con mod_wsgi de Apache, pero estando el Django dentro de un python con virtualenv.

En la documentación de Django explican el caso general de usar Django con Apache y mod_wsgi, incluyendo enlaces a otros documentos más extensos. Pero no explican el caso del virtualenv. Buscando en la web he encontrado muchos tutoriales pero ninguno me terminaba de aclarar. El problema es cómo decirle a mod_wsgi que coja el python del virtualenv en vez del global del sistema. Este tutorial es el que parecía más prometedor. Básicamente dice que hay que añadir el path del site-packages de nuestro virtualenv con una llamada site.addsitedir() y definir el path de python añadiendo WSGIPythonHome al fichero de configuración de Apache.

Sin embargo, la parte del site.addsitedir() sí funciona, pero el WSGPythonHome no. Después de mucho probar, descubrí que mod_wsgi necesita que el python del virtualenv esté en el path del sistema, si no, no lo encuentra aunque pongamos el WSGIPythonHome apuntando a él. Así que la solución es añadir /mi/path/virtualenv/bin al path, por ejemplo en el script  que lanza apache (normalmente será /etc/init.d/apache o /etc/init.d/httpd). Ojo con esto, que puede afectar a otros proyectos que usen python en el mismo apache.

Y observar una cosa importante: WSGI usa el mismo python para todos los virtual hosts, con lo cual se pierde una de las razones principales para usar virtualenv. Ahora esto sólo servirá si queremos aislar nuestro django de otros proyectos python que haya en el sistema, pero que no usen mod_wsgi.

Y otra cosa más: el mod_wsgi lanza el servidor en un directorio cualquiera, que no tiene por qué ser la raíz de Django. Para que encuentre las cosas, hay dos opciones: una es poner todos los paths absolutos en el settings.py, y la otra es añadir al principio del script django.wsgi las siguientes líneas:

import os
os.chdir(‘/mi/path/virtualenv/mi_proyecto/src’)

En este otro documento explica con bastante más detalle el comportamiento del wsgi script con Django.