I’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.
Hi,
I do almost the same thing, creating a local settings file that is not under version control, but I prefer not to import it, but to “append” it, with something like this in the end of settings.py:
This way, inside local.py I can use all the settings constants defined in settings.py, and override any too.
Yep, that’s also a good idea, but I – personally – don’t agree with overriding constants as it decreases code readability. Defining the same “constant” in different places throughout the application can become confusing.
PS: you can always use <pre lang=”python”> </pre> for your code.
Hi,
settings.py doesn’t have to be file. Django is a python application and settings is a module. You can create a settings directory with a __init__.py file in it. There you could separate the configurations in multiple files. In general I use the following files:
* environment – specific to deployed server
* django_app – specific to django (like MIDDLEWARE_CLASSES… )
* logger – hooks up the logging system from python
* application_name – application specific settings
Don’t forget to add from import * in the __init__ file.
I have in a configs directory the configurations for different environments. The deployment script knows what to copy to each server.
You can apply this approach with directories for modules to views.py, urls.py or models.py files.
I don’t say that this method is the best but it works for me.
Nice one. But you’re right, in the end, it matters more what works for you.