Blog Entry 13 years, 4 months ago

Configure Apache with multiple (non-root) Django sites

Django becomes quite inconvenient when you want to setup a site at non-root path of the domain. Thing goes more complex when there are more than one site in the same level (and maybe we have to add those dynamically.) There are some solutions working for the non-root issue

Django becomes quite inconvenient when you want to setup a site at non-root path of the domain. Thing goes more complex when there are more than one site in the same level (and maybe we have to add those dynamically.)

There are some solutions working for the non-root issue:

  • http://opensourcemissions.wordpress.com/2010/03/12/finally-a-working-django-non-root-url-with-mod_wsgi/
  • Using mod_wsgi or mod_python with declaration of parent environment
  • ...

Depending on the request, context and the personal habits, we could select or combine some solutions with the other. Below is what I've done to achieve it. Although I don't think it's optimized enough, it works.

1. Write an TemplateTag and some lines of Javascript for getting the current Django site ID/name and setting the appropriate cookie.

2. Put the combination of Javascript and TemplateTag above to the base.html of the site

3. Write the WSGI script

import os, sys
from os.path import dirname
os.environ['DJANGO_SETTINGS_MODULE'] = 'djsite.settings'
folders = []
folders.append(dirname(dirname(__file__)))
folders.append(dirname(folders[0]))
for folder in folders:
    sys.path.append(folder)
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

4. Configure Apache to make it talk with users and the Django sites

# set the virtual host, mod_rewrite,..

<VirtualHost django.vn:80>
    ServerName django.vn
    ErrorLog logs/subdjangos-error.log
    CustomLog logs/subdjangos-access.log common
    RewriteEngine On
    RewriteOptions MaxRedirects=10

# declare the first site: Foo

    Alias /foo/static/ /opt/subsites/foo/static
    <Directory /opt/subsites/foo/static>
        Order allow,deny
        Allow from all
    </Directory> 
    Alias /foo/media/ /opt/subsites/foo/media/
    <Directory /opt/subsites/foo/media>
        Order allow,deny
        Allow from all
    </Directory>
    RewriteCond %{REQUEST_URI} ^/((foo/.*$)|(foo$))
    RewriteRule ^ - [L]
    WSGIScriptAlias /foo /opt/subsites/foo/djsite.wsgi

# declare the second site: Bar

    Alias /bar/static/ /opt/subsites/bar/static
    <Directory /opt/subsites/bar/static>
        Order allow,deny
        Allow from all
    </Directory> 
    Alias /bar/media/ /opt/subsites/bar/media/
    <Directory /opt/subsites/bar/media>
        Order allow,deny
        Allow from all
    </Directory>
    RewriteCond %{REQUEST_URI} ^/((bar/.*$)|(bar$))
    RewriteRule ^ - [L]
    WSGIScriptAlias /bar /opt/subsites/bar/djsite.wsgi

# check and deal with existing cookie

    RewriteCond %{HTTP_COOKIE} dj_site_name=foo
    RewriteRule ^/(?!foo)(.*) /foo/$1 [R,L]  
    RewriteCond %{HTTP_COOKIE} dj_site_name=bar
    RewriteRule ^/(?!bar)(.*) /bar/$1 [R,L]
</VirtualHost>

OK, here are some explanations:

     RewriteCond %{REQUEST_URI} ^/((hello/.*$)|(hello$))
     RewriteRule ^ - [L]

The RewriteCond checks the request URI if bar/ is at the beginning or not. If True, Apache will cancel all other Rewrite lines and will pass the request to WSGIScriptAlias:

    WSGIScriptAlias /foo /opt/subsites/foo/djsite.wsgi

In case of not satisfied, the cookie (here is dj_site_name) will be checked for presence. That is the cookie which is set from the Javascript inside base.html

    RewriteCond %{HTTP_COOKIE} dj_site_name=foo
    RewriteRule ^/(?!foo)(.*) /foo/$1 [R,L]  

If the cookie value is "foo", all the requested URIs will be added with "/foo" as prefix. After redirection, WSGIScriptAlias will take the request and process it.

That is it.

Recent Reads