Ubuntu Hardy - Using mod_python to Serve Your Application

If you've followed the previous article you should have Apache and mod_python ready to serve an app for you.

In this article we'll create a basic Django app and setup the virtual host that will allow Apache and mod_python to work their magic.


Create the Django Application

First thing's first, move to your home directory and go into your public_html/domain1.com directory (if you don't have one, create one and of course give it the name of your domain rather than domain1.com):

cd ~/public_html/domain1.com

Next you'll want to create a Django project which is done simply with the django-admin.py tool.

In this case we will call it 'testproject':

django-admin.py startproject testproject

Create the Virtual Host

For Apache to be able to actually serve a Django application it needs to know that it should hand off certain requests to mod_python. To accomplish this, we'll setup a virtual host that takes care of letting Apache know what to do in certain situations.

This example is very basic but it will get you going:

sudo nano /etc/apache2/sites-available/domain1.com

Then type or copy the following virtual host definition:

<VirtualHost *:80>
        ServerName domain1.com
        ServerAlias www.domain1.com

        SetHandler python-program
        PythonHandler django.core.handlers.modpython
        SetEnv DJANGO_SETTINGS_MODULE testproject.settings
        PythonPath "['/home/demo/public_html/domain1.com'] + sys.path"
        PythonDebug On
</VirtualHost>

Once you've saved the virtual host you'll need to enable it and reload Apache:

sudo a2ensite domain1.com
sudo /etc/init.d/apache2 reload

Provided everything went as expected you should be able to visit your domain (or slice IP) in your browser and get your newly created Django application. It should look something like this:

Welcome to Django

Note: If you get any port and NameVirtualHost errors upon reloading Apache, please ensure you read the Apache Virtual Hosts article.

Static Content

There is a caveat to the virtual host definition provided, namely it does not allow serving of static content.

That is to say, no document root was specified and there is nothing to indicate that static files are not to be handled by mod_python and Django.

The Django team actually recommends you use a secondary web server to serve static content.

However, you can make a few tweaks in your testproject/settings.py file and use the following virtual host definition:

<VirtualHost *:80>
        ServerName domain1.com
        ServerAlias www.domain1.com

        SetHandler python-program
        PythonHandler django.core.handlers.modpython
        SetEnv DJANGO_SETTINGS_MODULE testproject.settings
        PythonPath "['/home/demo/public_html/domain1.com'] + sys.path"
        PythonDebug On

        DocumentRoot /home/demo/public_html/domain1.com
        <Location "/static/">
            SetHandler none
            Options -Indexes
        </Location>
</VirtualHost>

The Location block tells Apache to not let Django handle anything that's located under /static/ on your site. You can set this to be anything you like, but you'll need to make the appropriate directory available under /home/demo/public_html/domain1.com. In this example the directory would be called "static".

Tweaks for the settings.py file involve setting the MEDIA_URL and MEDIA_ROOT settings appropriately:

nano /home/demo/public_html/domain1.com/testproject/settings.py

Find the following two settings and edit them like so:

MEDIA_ROOT = '/home/demo/public_html/domain1.com/static/'
MEDIA_URL = '/static/'

Reload Apache now to make the updates take effect:

sudo /etc/init.d/apache2 reload

Now any items placed in /home/demo/public_html/domain1.com/static can be accessed via http://domain1.com/static/path/to/file.

Changes to your Django Application

When you update your python code or templates in a Django application with mod_python, you'll usually need to give Apache a reload to see the changes. So it's good to get into the habit of reloading Apache after making any changes to your project.

At this point you should now be able to successfully build out a Django application and have mod_python and Apache serve it up for you.

Ben H.

Article Comments:

Randy commented Fri Jul 17 15:28:26 UTC 2009:

Ben, I just walked thru the whole series on Django and while I was working on this tutorial I ran into this error.

VirtualHost :80 -- mixing * ports and non- ports with a NameVirtualHost address is not supported, proceeding with undefined results

I removed the default host and didn't have a problem continuing but I just wanted to point out the problem or find out if I did something wrong.

Ben H. commented Mon Jul 20 16:04:28 UTC 2009:

@Randy,

Yes that is an issue that may crop up. It was noted in the article as well:

"Note: If you get any port and NameVirtualHost errors upon reloading Apache, please ensure you read the Apache Virtual Hosts article."

You can fix it either the way you chose to or by the method outlined in the linked Apache article. Either way, you should be fine now that you've got it sorted out!

Thanks!

Sofia Cardita commented Fri Mar 26 17:51:21 UTC 2010:

Had the same error. Just add above the line with <virtualhost> this NameVirtualHost *:80.

Rich commented Tue Mar 22 23:59:12 UTC 2011:

If I have multiple sites, all running separate django apps,do I have to restart apache2 for all sites, or is there some way to just do like a restart of one of them?

Jered commented Wed Mar 23 18:23:20 UTC 2011:

You'll need to restart apache, as I understand it. You can use the "reload" or "graceful" argument when restarting apache to tell it to try to do a graceful restart. If you haven't done it before keep a close eye on the apps (for some apps graceful isn't that graceful), but that method should allow apache to finish off existing connections while starting new ones with the new settings at the same time. The old connections only get terminated when they're no longer in use.

The only other option I can think of offhand would be a complicated setup with a reverse proxy sitting in front of multiple web servers, each configured separately (so the proxy would channel connections to "domain1.com" to the server on port 81, "domain2.com" to an apache server running on port 82, and so on).

Want to comment?


(not made public)

(optional)

(use plain text or Markdown syntax)