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))
I found a couple of sets of instructions, although neither seemed to use the ‘django’ application type as described in WebFaction’s ‘Getting Started with Django’ guide.
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:
/home/username/webapps/django_application/myproject/
/home/username/webapps/django_application/myproject.wsgi
Then:
$ 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.
Then:
$ 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.
Finally:
(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.
Cron
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.
Comments
Commenting is disabled on posts once they’re 30 days old.
Luis Manuel at 11 Dec 2011, 5:13pm. Permalink
Sorry about my english:
My log is:
[Sun Dec 11 18:08:16 2011] [error] [client 127.0.0.1] connection = connections[DEFAULT_DB_ALIAS]
[Sun Dec 11 18:08:16 2011] [error] [client 127.0.0.1] File "/home/cemap/webapps/geofoc_django/lib/python2.7/django/db/utils.py", line 93, in __getitem__
[Sun Dec 11 18:08:16 2011] [error] [client 127.0.0.1] backend = load_backend(db['ENGINE'])
[Sun Dec 11 18:08:16 2011] [error] [client 127.0.0.1] File "/home/cemap/webapps/geofoc_django/lib/python2.7/django/db/utils.py", line 33, in load_backend
[Sun Dec 11 18:08:16 2011] [error] [client 127.0.0.1] return import_module('.base', backend_name)
[Sun Dec 11 18:08:16 2011] [error] [client 127.0.0.1] File "/home/cemap/webapps/geofoc_django/lib/python2.7/django/utils/importlib.py", line 35, in import_module
[Sun Dec 11 18:08:16 2011] [error] [client 127.0.0.1] __import__(name)
[Sun Dec 11 18:08:16 2011] [error] [client 127.0.0.1] File "/home/cemap/webapps/geofoc_django/lib/python2.7/django/db/backends/postgresql_psycopg2/base.py", line 9, in
[Sun Dec 11 18:08:16 2011] [error] [client 127.0.0.1] from django.db import utils
[Sun Dec 11 18:08:16 2011] [error] [client 127.0.0.1] TemplateSyntaxError: Caught ImportError while rendering: cannot import name utils
Many Thanks