I'm sure there's quite a few tutorials on this, and I'm sure what I have to say is nothing new to many people, but here is the pattern I follow, now, for app-specific settings in my distributable Django apps.
Basically, I use a settings.py in my app, in which it tries to grab its values from django.conf.settings using getattr.
The advantages of this approach are:
- Self documenting code Anyone wants to know what settings my app has, and their defaults, they're clearly apparent.
- Central definitions. You only have to look at one place to find all the settings.
- Prevents circular imports. This is what actually triggered me to move to this in the first place.
Here is an example taken from gnocchi-cms:
from django.conf import settings import os.path # For Views PAGE_CACHE = getattr(settings, 'PAGE_CACHE', 60*60*24) DEFAULT_TEMPLATE = getattr(settings, 'DEFAULT_TEMPLATE', 'default.html') # For Admin STATIC_URL = getattr(settings, 'STATIC_URL', settings.MEDIA_URL) CODEMIRROR = getattr(settings, 'CODEMIRROR', os.path.join(STATIC_URL, 'codemirror')) WYMEDITOR = getattr(settings, 'WYMEDITOR', os.path.join(STATIC_URL, 'wymeditor')) # For Context Variables CV_NAMESPACE = getattr(settings, 'CV_NAMESPACE', 'cv') CV_CACHE_TIME = getattr(settings, 'CV_CACHE_TIME', 24*60*60) # Sites Middleware IGNORE_WWW_ZONE = getattr(settings, 'IGNORE_WWW_ZONE', True) IGNORE_SERVER_PORT = getattr(settings, 'IGNORE_SERVER_PORT', True)
Now, just looking at this code it's immediately clear what all the settings are, their defaults, and even which parts of the code they're for.
Addendum and Caveat
I discovered today, in my first Django 1.3 site, that settings can trick you.
It looks like it will return None to getattr if it's an attribute it knows (the one that got me was STATIC_URL).
My work around in gnocchi-cms has been:
STATIC_URL = getattr(settings, 'STATIC_URL') if STATIC_URL is None: STATIC_URL = settings.MEDIA_URL