Friday, May 13, 2011

Deploying a Django app with Apache and mod_wsgi

At work recently I've been deploying a small Django app. It's taken quite a long time. Most of the time things have been moving forward nicely but every now and then there has been some misleading detail in some instruction which has made me stand in place for a long time.

In a nutshell (on Ubuntu)




  • Apache needs the mod_wsgi module

  • Use the WSGIScriptAlias directive to point to the location of your project's .wsgi file

  • Point to your settings in the .wsgi file



This procedure is described in How to use Django with Apache and mod_wsgi

Complications




  1. I used virtualenv to prevent the installed modules from conflicting with other modules. This meant I had to follow the Virtual Environments section of mod_wsgi's wiki. You don't have to follow these instructions precisely. The instructions are aimed at preventing system-wide modules from shadowing/overriding modules in your virtualenv. Simply using site.addsitedir with the virtualenv's site packages directory worked for me.



  2. NOTE! The instructions in Django's docs also neglected to mention that you have to append two paths to your sys.path. You have to append both your project's path as well as the project's parent's path. If you don't add the parent you can't specify os.environ['DJANGO_SETTINGS_MODULE'] prefixed with your project's name. If you don't add the project itself you can't import the apps inside it.



  3. The server that was going to run the web app only had Python 2.4 installed. I wanted to make sure that my development environment would be reasonably close to the production environment. Installing an older version of python was very easy. All you had to do was use make altinstall instead of make install. However, now you also need to compile the mod_wsgi module manually. You use the --with-python=/usr/local/bin/python2.4 configure flag to specify which version to compile for. Then when you make the module it ends up in a hidden .libs folder. Move it from there to Apache's modules folder. I chose to rename it to wsgi_2.4.so or something so it wouldn't overwrite the module installed by apt-get earlier. Check some .load file from your /etc/apache2/mods-available/ for reference. Then you can add your own wsgi_2.4.load and wsgi_2.4.conf files to mods-available and use a2enmod to enable it. Now since you are using your own vintage Python version you have to additionally use the WSGIPythonHome /usr/local/ (or something, my mind is a bit unsure of this detail at the moment) directive to specify the prefix to your Python installation.



  4. Finally if you are serving static content (css, images, js etc.) you should be doing that straight with your web server instead of through Django. Django has a very nice app called django.contrib.staticfiles which through adding STATIC_URL to your settings.py file, adding django.core.context_processors.static to TEMPLATE_CONTEXT_PROCESSORS and prefixing your static urls with {{ STATIC_URL }} allows you to easily serve files with runserver. Then for production use you will want to set up the STATIC_ROOT variable in settings.py, put application-specific media in a static folder and run manage.py collectstatic to have all your media files transferred into the STATIC_ROOT. Now you can serve the files from this location by using the Alias directive in Apache for example.



I felt way more l33t when I had to set up the 2.4 version of Python manually than by simply installing everything through apt-get like a n00b.

No comments:

Post a Comment