Using relative paths in your settings.py

Several important settings in your [Django project’s
settings.py][settings] are annotated with warnings about the need for
absolute path names. When I start a new project with the development
server I don’t want to have to think what directory my MEDIA_ROOT should
point to. Isn’t all that going to change anyway when it’s deployed to
the gigantic server in the sky?

[settings]: http://www.djangoproject.com/documentation/settings/

My first tip is that when you are running the development server, you
*can* get away with relative paths. Paths will be relative to the
directory you were in when you started the development server (in my
case I always `cd ~/my_project && ./manage.py runserver` so that
means relative to my project’s directory).

Therefore if you want to keep project-wide templates within the project,
just create a `templates` directory and add it to settings.py:

TEMPLATE_DIRS = (
‘templates’,
)

Sweet! Relative paths and it all works and I don’t have to edit my
`TEMPLATE_DIRS` setting whenever I am editing on a work machine (where
the project is in `/Users/dbuxton/my_project`) instead of home (where
the project is in `/Users/david/my_project`).

But it all goes pear-shaped when you move the project to the deployment
platform. There the project is running under mod_python where the notion
of the current working directory is going to be very different. All I
know is my relative paths *do not get resolved* and I wonder if them
Django developers knew a thing or two when they warned me to use
absolute paths.

My current approach to this is to refuse to do what I am told. Instead
one can take advantage of a [Python module’s `__file__` attribute][__file__] to establish where on disk your `settings.py` is,
and armed with that knowledge you can construct absolute paths from the
relative settings.

[__file__]: http://www.python.org/doc/2.5.1/ref/types.html#l2h-111

Near the top of `settings.py` I have:

import os

INSTALL_DIR = os.path.dirname(os.path.abspath(__file__))

Then anywhere I need an absolute path in settings.py I have something
similar to this:

TEMPLATE_DIRS = (
os.path.join(INSTALL_DIR, ‘templates’),
)

Shabooba! These paths change according to the value of `INSTALL_DIR`,
and that in turn is determined when the Django project is loaded. When
my project’s templates are sitting on a distant FreeBSD server in
`/home/webapps/django/my_project/templates` mod_python can locate them
just as surely as Django’s development server can locate the folder
`/Users/david/my_project/templates` on my MacBook.

Leave a Reply

Your email address will not be published. Required fields are marked *