Today I set up a site on WebFaction’s hosting for the first time. Initially it was lovely — the control panel makes it easy to set up a wide arrange of different kinds of hosting environments. I got pip and virtualenv working fine, but I wasn’t sure how to have the site run within a virtualenv.
(Having written all of that, I’m not sure if it’s ideal… why have I set up an application of type ‘django’ when I want to use my own particular copy of Django within my virtualenv? Maybe I should try and follow these instructions for doing this with a ‘mod_wsgi’ application, even though that seems a little more complicated? (28 June 2011))
After much trial and error, here’s the solution I came up with. Any suggestions for improvements are very welcome as I’m sure this could be better.
This guide assumes you’ve probably used pip and virtualenv/virtualenvwrapper before and just want to get it working on WebFaction. You’ve followed the ‘Getting Started with Django’ guide, which will have created:
$ easy_install virtualenv $ easy_install pip $ pip install virtualenvwrapper $ mkdir ~/.virtualenvs $ vim ~/.bashrc
Add these lines at the end of .bashrc:
export WORKON_HOME=$HOME/.virtualenvs source /home/username/bin/virtualenvwrapper.sh export PIP_VIRTUALENV_BASE=$WORKON_HOME # Tell pip to create its virtualenvs in $WORKON_HOME. export PIP_RESPECT_VIRTUALENV=true # Tell pip to automatically use the currently active virtualenv.
$ source ~/.bashrc $ mkvirtualenv --no-site-packages --distribute my_env_name
Obviously, with a meaningful name instead of ‘my_env_name’. Now we’re working within that virtual environment. Note: The version of Python that your virtualenv uses by default may be different from the one your Django app is set to use. You can make it use a specific version by adding something like ‘-p python2.6’, e.g.:
$ mkvirtualenv --no-site-packages --distribute -p python2.6 my_env_name
Assuming that version of Python installed on your system. (Type “python” and then tab a couple of times to see the options.)
Install any things you need. eg:
(my_env_name)$ pip install yolk
Or install from a pip requirements file from an existing project:
(my_env_name)$ pip install -r REQUIREMENTS.txt
Then, the bit that took me ages to work out, edit ~/webapps/django_application/myproject.wsgi. I don’t know if all of these are required, but it seems to work for me…
import os, sys, site # Tell wsgi to add the Python site-packages to its path. site.addsitedir('/home/username/.virtualenvs/my_env_name/lib/python2.6/site-packages') os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.settings' activate_this = os.path.expanduser("~/.virtualenvs/my_env_name/bin/activate_this.py") execfile(activate_this, dict(__file__=activate_this)) # Calculate the path based on the location of the WSGI script project = '/home/username/webapps/django_application/myproject/' workspace = os.path.dirname(project) sys.path.append(workspace) from django.core.handlers.wsgi import WSGIHandler application = WSGIHandler()
Obviously, replace ‘username’, ‘my_env_name’, ‘django_application’ and ‘myproject’ as appropriate.
(my_env_name)$ cd ~/webapps/django_application/myproject/ (my_env_name)$ python manage.py syncdb (my_env_name)$ ../apache2/bin/restart
You’ll need to do that last line every time you make a change to myproject.wsgi.
Getting a Django manage.py command to run via cron seemed tricky. The best way seems to be to make a bash script to run what you want. Something like this:
#! /bin/bash source $HOME/.virtualenvs/my_env_name/bin/activate $HOME/webapps/django_application/myproject/manage.py commandname
Obviously, replace ‘commandname’ with whatever command you want to run. And you can have multiple lines of that. Then type ‘crontab -e’ to edit the cron file and add something like:
15 * * * * $HOME/cron.sh > $HOME/cron.log 2>&1
Where you can replace cron.sh with the path and filename to wherever your bash script is. Everything from the > onwards tells it to send output to a log file of your specifying. Omit that if you like.