Since the topic resurfaces routinely let me summarise why you might want to consider this approach:
a dumb settings file is very fast and easy to change; especially in a production environment. No python required: any idiot can jump in and change the database password in a file which just lists names and values; especially compared to a complex python settings file full of mysterious dangerous BIGCAPS names.
the application settings
should be completely separated from the application code
. You can put a config.ini outside the repository root and never again worry about a repo pull clobbering your settings, or your personal settings polluting the repo, or that clever code in your settings.py not making it into the repo to everyone else's advantage.
This won't apply to small projects, but on bigger projects I've concluded that the local_settings strategy just doesn't cut it; over time enough application programming creeps in that it gets hard to handle; primarily as settings become derivative and/or codependent. There can be good justifications for settings to react according to the local settings which forces the import of a local_settings
file to creep up toward the middle of settings.py
. I find things start to get messy as that happens.
My current solution is to use a config
file, I dub it "local.ini". It holds only those values which do actually change between deployed instances. There is no code: they are just values and booleans:
[global]
domain = 127.0.0.1:8000
database_host = 127.0.0.1
database_name = test_database
debug = Yes
google_analytics_id = UA-DEV-1
payments = testing
use_cdn = No
With this in place I can treat the settings.py
like any other piece of application code: tweak it, check it in, and deploy it without having to worry about testing against whatever code might be lurking in a local_settings python code. My settings.py
is free of race conditions that come up when later settings depend on local settings, and I can switch features on and off writing easy-to-follow linear code. No more hurriedly tweaking the local_settings file when I've forgotten to add some new value, and no more daves_local_settings.py
and bobs_local_settings.py
files creeping into the repository.
from ConfigParser import RawConfigParser
parser = RawConfigParser()
APPLICATION_ROOT = path.abspath(path.dirname(__file__))
parser.readfp(open(path.join(APPLICATION_ROOT, 'local.ini')))
# simple variables
DATABASE_HOST = parser.get('global', 'database_host')
DATABASE_NAME = parser.get('global', 'database_name')
# interdependencies
from version import get_cdn_version
CDN = 'd99phdomw5k72k.cloudfront.net'
if parser.getboolean('global', 'use_cdn'):
STATIC_URL = '/{}/static/{}/'.format(CDN, get_cdn_version())
else:
STATIC_URL = '/static/'
# switches
payments = parser.get('global', 'payments')
if payments == 'testing':
PAYMENT_GATEWAY_ENDPOINT = 'https://api.sandbox.gateway.com'
else:
PAYMENT_GATEWAY_ENDPOINT = 'https://api.live.gateway.com'
If you encounter a BOFH, like I had on one occasion, he got particularly excited about the ability to stick the local.ini
into the /etc
directory as /etc/ourapp.ini
and so keep the application directory itself a pure repository export. Sure you could do that with a local_settings.py but the last thing he wanted to do was mess with python code. A simple config file he could handle.