django web frameworkI’ve been using Django for quite some time now and I kind of like it. It provides a fast – really fast – and clean way of doing things. When I first started with Django, I’ve used it mainly for simpler projects and kept the larger, more complicated ones on Zend Framework. That’s because I feel much more comfortable with PHP and Zend Framework rather than python and Django.

But, lately, I’ve used django for more ambitious projects and some obvious flaws began to annoy me. The first thing – the one this entry’s about – is the configuration file. Django comes with a settings.py file in which all the settings are being held, without any regard to their purpose.

Environment settings like database connection strings, file system paths and debuging are mixed together with application settings like what middleware classes are used, context processors and so on. So I’ve decided to split the configuration file in two, like in the following example:

local.py

This file holds the host related configuration and each instance of the application should have its own local.py file. One for development, one for testing, one for staging, one for production and so on. This file should not be included in the source control repository, so add a svn/git/whatever ignore on it.

# debug settings
DEBUG = True
TEMPLATE_DEBUG = DEBUG

# database configuration
DATABASE_ENGINE = ''
DATABASE_NAME = ''
DATABASE_USER = ''
DATABASE_PASSWORD = ''
DATABASE_HOST = ''
DATABASE_PORT = ''

# media root ex: /var/www/my-project/media
MEDIA_ROOT = ''

# media url ex: media.my-project.tld
MEDIA_URL = ''

# admin media url ex: /media
ADMIN_MEDIA_PREFIX = '/media/'

# application's secret key
SECRET_KEY = 'mY-S3Cr3t-K3y-m|_|st-b3-un1QuE-4nD-h4rD-t0-GueSs'

settings.py

This file holds the application related configurations and should be included in the version control system.

import os

# root directory for the project
ROOT_DIR = os.path.realpath( os.path.dirname( __file__ ) )

ADMINS = (
	( 'root', 'root@project.tld' ),
)

# import all the local settings
from local import *

MANAGERS = ADMINS
TIME_ZONE = 'Europe/Bucharest'

LANGUAGE_CODE = 'en-us'

SITE_ID = 1

USE_I18N = True

TEMPLATE_LOADERS = (
    'django.template.loaders.filesystem.load_template_source',
    'django.template.loaders.app_directories.load_template_source',
)

MIDDLEWARE_CLASSES = (
    'django.middleware.cache.UpdateCacheMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.middleware.cache.FetchFromCacheMiddleware',
)

ROOT_URLCONF = 'my-project.urls'

TEMPLATE_CONTEXT_PROCESSORS = (
    'django.core.context_processors.auth',
    'django.core.context_processors.debug',
    'django.core.context_processors.i18n',
    'django.core.context_processors.media',
)

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
)

# template directories
TEMPLATE_DIRS = (
    os.path.join( ROOT_DIR, 'templates' ),
    os.path.join( ROOT_DIR, 'other', 'template', 'path' ),
)

# django debug toolbar configuration
INTERNAL_IPS = ( '127.0.0.1' )
if DEBUG:
    MIDDLEWARE_CLASSES += 'debug_toolbar.middleware.DebugToolbarMiddleware',
    INSTALLED_APPS += 'debug_toolbar',

The last bit is because I usually use in development the incredibly useful Django debug_toolbar, and of course, I want it turned off on the live environment.