Django Settings for Production and Development: Best Practices
It's annoying how there is no canonical way to do it. You need to spend some mental energy learning how to do this when starting up a Django project. Django should really integrate one solution into the django core, and then everyone can just use that. Make it much easier.
A fourth way: the django config is a template, with entries like:
settings.py:
Yes, that's a django template in python code. Upon deployment, my fabfile renders the settings file along with various other config files. This makes sure that {{MEMCACHED_PORT}} doesn't accidentally say one thing in settings.py, and another in memcached.conf.CACHES = { 'default': { 'BACKEND' : 'django.core.cache.backends.memcached.MemcachedCache', 'LOCATION' : [ {% for IP in MEMCACHED_SERVERS %}'{{IP}}:{{MEMCACHED_PORT}}', {% endfor %} ], },This also allows me to keep my sitewide settings in a single file or two, namely a module in the fabfile folder.
It feels a little dirty to do things this way (though I can't figure out why), but it's saved me a lot of headaches.
Seems complicated. I always use four simple files:
Where the first one has the defaults (usable for local development), and the others contain any overrides needed to run with Gunicorn on the corresponding dev/staging/production servers.settings.py settings_development.py settings_staging.py settings_production.pyI have a common settings.py file which starts with:
Then I have alex.py, prod.py and test.py all in a config subfolder. All under version control, with my settings.py automatically choosing the right environment based on where it's deployed to.ROOT_PATH = os.path.dirname(os.path.abspath(__file__)) configs = { '/path/to/my/local/dev/folder': 'alex', '/var/www/www.mywebsite.com/test/private/django/mywebsite': 'test', '/var/www/www.mywebsite.com/prod/private/django/mywebsite': 'prod' } config_module = __import__('config.%s' % configs[ROOT_PATH], globals(), locals(), 'mywebsite') for setting in dir(config_module): if setting == setting.upper(): locals()[setting] = getattr(config_module, setting)a lot more information here https://code.djangoproject.com/wiki/SplitSettings
I typically use this set up:
- settings.py contains global settings that aren't effected by deployment level.
- at the bottom of that file you have
- in settings_local.py you have your deployment level dependent settingstry: from settings_local import * except: pass- then just git ignore settings_local.py
I toss most of my core settings into the settings folder and __init__.py and then from there in my development.py, staging.py production.py
I can then, in each of my specific environment files just from settings import * and have access to the direct variables for all of my __init__.py items I setup. Most of the time you'll just have different database and cache settings for these environments.
Before you yell at me about the * import, yes, it normally is a bad idea but in this case it is good. It does often get abused and that is why so many people see it was "bad".
I like how Heroku does it, it's very smart, they basically inject the database settings to your settings.py that code just grabs the connection settings from the environment so you don't need to worry about it.
More info: http://devcenter.heroku.com/articles/django
OK, HN front page effect, the server crapped out. Any advice on how to handle this? Cannot even SSH on the server.
For the first one, another disadvantage (mentioned but not as a disadvantage) is that local_settings is not under version control.