How to run a Django site in a subdirectory

2016-02-26 | #django, #solution, #webdev

This is a reoccurring problem with Django projects, that does not seem to have a default way of solving it. Most people tend to recommend building a prefix for your URLs and all statics that get delivered from an absolute path. This is cumbersome and fails if your are using solutions such as the internationalization in Django CMS, because its middleware does things of its own to all URLs. Now what?

Actually there's a feature for this, that's, very Django-unlike, extremely badly documented. As you know Django applications get delivered via WSGI, over the projects When you set up the delivery of that file in a server of your choice, you can define under which path the application will be reachable. That's called the script name and virtually IS the subdir for the site.

Django now uses that script name as a base for all routing and URL construction. If you can't be sure that the server provides the script name correctly you can even set it by force in your like this (take note of the leading '/'):

FORCE_SCRIPT_NAME = '/yoursubdir'

You can even retroactively set the script name in you like this:

import os

from django.conf import settings

os.environ['SCRIPT_NAME'] = settings.FORCE_SCRIPT_NAME

This should handle all subdir routing and offer you the possibility to handle remaining manual tweaks via your settings constant.

Attention: Using Djangos runserver, Django CMS and a FORCE_SCRIPT_NAME different from '' may result in a redirect loop! You can verify your settings nonetheless quite easily by using gunicorn locally. Just install "gunicorn" via pip and call it like this:

gunicorn --env SCRIPT_NAME=sagjazufarbe --env SERVER_TYPE=gunicorn --reload yourproject.wsgi

Here you can see how to provide a script name with gunicorn. I also set a SERVER_TYPE here to be able to automatically handle runserver vs. gunicorn in the settings as well as "--reload" to get autoreloading on python source changes while debugging.