Django, mod_wsgi, Apache and OS X
Pretend Deployment Environment
There I was a few weeks ago (or was it months? years? no…) merrily working my way through Python Web Development with Django when I got to Chapter 7 and a Note that says the chapter assumes apache and mod_python setup, or some other deployment strategy, since the handy dandy development server doesn’t really cut it for the (toy) photo gallery. See appendix.
I bet the django development server will work just fine for the exercise, and plan to try it out, but on the other hand I was happy to try running django with apache since that is what we do at work and one reason I am working through the book on my own time is to better understand the systems I manage at work. The appendix mentioned wsgi as an alternative and again, since that is what we use at work, I went that way.
Good Enough
Or at least I tried to go that way… then I got lost, then back on track, then interrupted for days or weeks, and eventually with help from these two pages (1, from Chris, 2, from jesse ) I got it working perfectly! Though I believe configured rather badly, which is to say I barely understand it and have some ideas about how to understand it better and make it better, listed below. But to avoid losing my place again, here are the key bits that I know about that matter.
I do not recommend these bits as a good solution, merely as a waypoint on my learning path and an existence proof that it is possible to get it working.
In httpd.conf:
LoadModule wsgi_module libexec/apache2/mod_wsgi.so Include /private/etc/apache2/extra/httpd-vhosts.conf
I do not think it is necessary to use a virtual host, but that is the path I was on when I got it working. The instructions from jesse (which I forgot about today until after I got it mostly working) show how to put all the configuration info in a conf file in your django project and then include it in httpd.conf. But I put it in httpd-vhosts.conf and included it instead.
In /etc/hosts:
127.0.0.1 localhost mymach
In httpd-vhosts.conf:
<VirtualHost *:80>
ServerName mymach
ErrorLog "/private/var/log/apache2/mymach-error_log"
CustomLog "/private/var/log/apache2/mymach-error_log" common
<Directory /Users/marla/Projects/wdsite>
AllowOverride All
Options Indexes FollowSymLinks
Order allow,deny
Allow from all
</Directory>
Alias /adminmedia/ "/Library/Python/2.6/site-packages/django/contrib/admin/media/"
<Directory "/Library/Python/2.6/site-packages/django/contrib/admin/media">
Order allow,deny
Options Indexes
Allow from all
IndexOptions FancyIndexing
</Directory>
WSGIScriptAlias / "/Users/marla/Projects/wdsite/wdsite.wsgi"
</VirtualHost>
In settings.py:
# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a # trailing slash. # Examples: "http://foo.com/media/", "/media/". ADMIN_MEDIA_PREFIX = '/adminmedia/'
Note that the error file mymach-error_log was very useful in getting this working. At one point I was getting this error message:
[Sat Aug 07 17:21:34 2010] [error] [client ::1] mod_wsgi (pid=14756): Target WSGI script '/Users/marla/Projects/wdsite/wdsite.wsgi' cannot be loaded as Python module.
The suggested test described here that was supposed to fail actually worked for me, which was amusing but also informative because it meant that the problem was not a python problem. It turned out to be a sys.path problem which I hackily solved like so in my wdsite.wsgi file:
sys.path.append('/Library/Python/2.6/site-packages')
If I had not installed mod_wsgi.so using macports and then moved it over to /usr/libexec/apache2 because I wanted to use the apache installed with Snow Leopard, probably it would have looked for django in the right place without me telling it.
Improvements List
- The biggest thing I know I want to change is to use virtualenv. That will probably include reinstalling mod_wsgi properly. I would like to make a script that can set up the environment properly from scratch, too. I think it would be fun to deploy the With Django chapter exercises on our family website hosted by HostGator.
- In ch 7 of the book, the media dir inside the django project has an admin symlink to the installed django/contrib/admin/media, which seems nicer to me than the alias defined above in the httpd-vhosts.conf file going directly to the installed django. Maybe I will try that before doing the virtualenv, but I hope that is one of the many things that will be nicely encapsulated by a virtualenv.

That suggested test you referenced was likely for a completely different error, namely ‘ImportError: DLL load failed: The specified module could not be found. ‘. Specifically, issues with import _socket module. That problem is Windows specific, so you couldn’t have been getting it on a Mac. Thus no surprise it worked
BTW, I really suggest you read the actual mod_wsgi documentation rather than rely on blogs of people who have nothing to do with mod_wsgi project.
Thus, go read:
http://www.modwsgi.org
There is a lot of documentation there to be found.
In respect of virtual environments, see:
http://code.google.com/p/modwsgi/wiki/VirtualEnvironments
Take note of comments in:
http://code.google.com/p/modwsgi/wiki/IntegrationWithDjango
which specifically talk about sys.path issues with Django. Also take note of where it says is the best place to stick your WSGI script file.
Finally, go watch the mod_wsgi talk, which uses Django as an example:
http://blog.dscpl.com.au/2010/06/sydney-pycon-modwsgi-talk-slides.html
Thanks so much, Graham, for the detailed rtfm. I really appreciate it!
Putting your suggestions at the top of my reading list might help me stay engaged in my studies this week. Normally all my energy is sucked into my day job until I quit early on Friday to study.