Category Archives: Blog

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.

My Mac is broken: Spotlight example 1

Gah.

Just thinking about having to find files on a Macintosh fills me with dread. Spotlight is useless for finding anything unless you know where it is already. I am in the half of the Venn diagram labelled *believes names of files and folders have meaning*. In the other half are the interface designers of [Apple’s Spotlight technology][spotlight].

Here’s a plum example of how a Spotlight window in Mac OS X 10.5.3 does an alphabetic sort-by-name of results when searching for files using *File Name* criteria.

Spotlight's notion of an alphabetical sort

I hate Spotlight. Makes me wonder what the point of all that amazing search engine technology is.

[spotlight]: http://developer.apple.com/macosx/spotlight.html
[pic]: http://reliablybroken.com/b/wp-content/uploads/spotlight-broken-1.gif

Old-style Python class system and parent methods

I rather like Python’s explicit object reference requirement, whereby method definitions for a class instance have to use `self` as the first parameter (I should write some classes that use `this` instead of `self` some time, just to annoy myself).

But I was tripped up debugging a problem that centred on a simple class I had that needed to do a bit of housekeeping for byte streams:

from StringIO import StringIO

class MyString(StringIO):
def __init__(self, *args, **kwargs):
self._customized = True # Or similar housekeeping
super(MyString, self).__init__(*args, **kwargs)

Creating an object from this class raises a `TypeError`:

>>> s = MyString()
Traceback (most recent call last):
File “”, line 1, in
File “”, line 4, in __init__
TypeError: super() argument 1 must be type, not classobj

Wuh? I always used `super` like that before, and it always worked. But my mistake here was I was sub-classing an [*old-style* class][old], and `super` only works with [*new-style* classes][new].

The correct way of calling the parent method for old-style classes:

class MyString(StringIO):
def __init__(self, *args, **kwargs):
self._customized = True # Or similar housekeeping
StringIO.__init__(self, *args, **kwargs)

That works! But the distinction between the two class models is so inelegant, so clunky. It is a nasty bit of Python’s historic implementation that one needs to keep in mind, and it is knowledge that makes me no cleverer (although it does mean I’m less stupid than I was).

Of course Python 3000 removes this distinction…

[old]: http://docs.python.org/ref/node33.html
[new]: http://docs.python.org/tut/node11.html#SECTION0011500000000000000000

Humour in FreeBSD man pages

Was reading the [tunefs man page][tunefs] today while working out how to enable ACLs for a filesystem in [FreeBSD][freebsd]. The last line made me laugh.

> You can tune a file system, but you can’t tune a fish.

The man pages are one of the BSD’s great strengths.

[tunefs]: http://www.freebsd.org/cgi/man.cgi?query=tunefs
[freebsd]: http://www.freebsd.org/