Entries tagged with apache rss

mod_wsgi and virtualenv for multiple django versions

I'm converting a mod_python environment to a mod_wsgi one. I was using the debian packages for both django-tagging and django itself. This has proved to be unacceptable both for upgrades and for keeping sites running. I don't want an apt-get dist-upgrade to break all my django sites (as it did yesterday).

One solution to this is to use virtualenv to keep separate python environments for each site, and then upgrade them individually as necessary. It wasn't clear how mod_python would work with virtualenv (I tried), so I moved to using mod_wsgi which is also reputed to be more efficient. To begin, install both virutalenv and mod_wsgi:

apt-get install python-virtualenv libapache2-mod-wsgi

Next, set up virtualenv. In the project directory (described previously), run:

virtualenv --no-site-packages --unzip-setuptools ENV

Next, grab django and whatever other packages you might want. I move these to a directory with the SVN revision after the package name.

cd ~/libs/ svn co http://code.djangoproject.com/svn/django/trunk/ django mv django django-10645 svn checkout http://django-tagging.googlecode.com/svn/trunk/ tagging mv tagging tagging-154

Symlink the packages in to the virtual environment.

cd ~/libs/django-10645 ln -s `pwd`/django /home/username/blog/ENV/lib/python2.5/site-packages/ cd ~/libs/tagging-154 ln -s `pwd`/tagging /home/username/blog/ENV/lib/python2.5/site-packages/

Create the wsgi config file. This goes in a separate directory from everything else so that the permissions that apache has to read and serve it don't affect anything else.

mkdir ~/blog/apache vi ~/blog/apache/blog.wsgi

The wsgi file should look like the following. Bolded are the parts which will be changed for each project.

ALLDIRS = ['/home/username/blog/ENV/lib/python2.5/site-packages/'] import os, sys, site prev_sys_path = list(sys.path) for directory in ALLDIRS: site.addsitedir(directory) new_sys_path = [] for item in list(sys.path): if item not in prev_sys_path: new_sys_path.append(item) sys.path.remove(item) sys.path[:0] = new_sys_path sys.path.append('/home/username/blog/projects/') os.environ['PYTHON_EGG_CACHE'] = '/home/username/.python-eggs' os.environ['DJANGO_SETTINGS_MODULE'] = 'blogsite.settings' import django.core.handlers.wsgi application = django.core.handlers.wsgi.WSGIHandler()

My version seems to differ slightly from other versions I've seen. In particular my "main site" app is in a subdirectory of projects, so I have appname.settings for the DJANGO_SETTINGS_MODULE. I'm not sure that my way has any advantage over any others, it's just the way it is.

Finally, set up the virtual host:

<VirtualHost XXX.XXX.XXX.XXX> ServerAdmin admin@example.com ServerName blog.example.com CustomLog /var/log/apache2/access.log combined Alias /adminmedia /home/username/blog/ENV/lib/python2.5/site-packages/django/contrib/admin/media Alias /media /home/username/blog/media <Directory /home/username/blog/apache/> Order deny,allow Allow from all </Directory> WSGIDaemonProcess blog.example.com user=www-data group=www-data threads=25 WSGIProcessGroup blog.example.com WSGIScriptAlias / /home/username/blog/apache/blog.wsgi </VirtualHost>

First, two aliases are set, one for the normal media (this is unchanged from a mod_python installation) and the other for the admin media. This should point to the virtualenv version of the admin media. Next, the Directory section allows apache access to the wsgi handler. And finally, wsgi is configured and pointed to the handler in the apache directory. Do a:

apache2ctl restart

And it's done!

apache2/mod_python configuration for django

The request for a working apache/mod_python configuration example comes up frequently on the django IRC channel. Usually a bad configuration is the underlying problem when admin media doesn't show up or when projects are not found on the python path. This is the model I use:

<VirtualHost xxx.xxx.xxx.xxx> ServerAdmin admin@example.com DocumentRoot /home/username/projectname/public_html/ ServerName example.com CustomLog /var/log/apache2/access.log combined Alias /adminmedia /usr/share/python-support/python-django/django/contrib/admin/media Alias /media /home/username/projectname/media <Location "/"> SetHandler python-program PythonHandler django.core.handlers.modpython PythonPath "['/home/username/projectname/projects/'] + sys.path" SetEnv DJANGO_SETTINGS_MODULE mysite.settings PythonDebug On </Location> <Location "/media"> SetHandler None </Location> <Location "/adminmedia"> SetHandler None </Location> </VirtualHost>

This is for a directory layout like this:

/home/username/projectname/ <- your project directory /home/username/projectname/media/ <- media /home/username/projectname/public_html/ <- empty, a harmless place to point apache /home/username/projectname/projects/ <- where all your projects live /home/username/projectname/projects/mysite/ <- your main project/app

Inside mysite/, you have settings.py. In settings.py, you've set MEDIA_ROOT = '/home/username/projectname/media/' and MEDIA_URL = '/media/' and ADMIN_MEDIA_PREFIX = '/adminmedia/'.

When django admin won’t start

You've just installed django and set up your first project. You can't get to the admin. Why?

You're using sqlite and didn't create a database file.

$ touch database.db

You're using sqlite and didn't specify the full path to your database file in settings.py.

DATABASE_NAME = '/home/user/projects/mysite/database.db'

You're using sqlite and you didn't give apache sufficient permissions to access the DB or the project directory.

$ cd /home/user/projects/mysite/ $ chgrp www-data . database.db $ chmod g+w . database.db

You forgot to enable admin in settings.py.

INSTALLED_APPS = ( ... 'django.contrib.admin', ... )

You forgot to syncdb after enabling admin.

$ ./manage.py syncdb