A Different Approach to local_settings.py
A couple weeks ago when I spoke at Django NYC, in one of my slides I introduced the local_settings.py trick for Django, and on the next slide I mentioned a slight variant on the standard trick, which I've tried to introduce before, but the idea got lost in the midst of the longer article.
The Real local_settings.py
The original version of this trick is simple and extremely
useful. At the bottom of your settings.py
file, add these
four lines
try:
from local_settings import *
except ImportError:
pass
Then you can create a custom local_settings.py
file
with overrides for the settings for your machine, and
you're golden.
When you're creating public repositories, you make sure not
to place your local_settings.py
into the version control,
but you can still create a local_settings.py.template
file
that others cp local_settings.py.template local_settings.py
and then edit to their liking.
The Variant I Speak Of
The first time I used this variant I was working on an app which I deployed two places: on my VPS and on my personal machine. I wanted to be able to keep the settings for both in version control, but without any needing to make modifications each time I updated the checked out project.
My solution went like this:
Have the
settings.py
file which contains all shared settings, and still ends with:try: from local_settings import * except ImportError: pass
Store the settings for my development machine in
devel_settings.py
and store the settings for VPS invps_settings.py
.On each development, create a
local_settings.py
file that only contained one line. For my development server the line is:from devel_settings import *
and for my VPS the line is:
from vps_settings import *
Doing that, I can easily modify both setups and keep them in version control incase I want to deploy the project on another machine.
Essentially what's being done here is something akin to subclass settings files and overriding just what is necessary. You can get carried away with this stuff if you want to, and have a settings buffet where you combine pieces as you like.
For example, you could have a file named site_caching_settings.py
that looks like this:
CACHE_BACKEND = "memcached://127.0.0.1:11211/"
CACHE_MIDDLEWARE_SECONDS = 60 * 30
CACHE_MIDDLEWARE_KEY_PREFIX = "scs"
CACHE_MIDDLEWARE_ANONYMOUS_ONLY = True
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.middleware.cache.CacheMiddleware',
) + MIDDLEWARE_CLASSES
and you could have a file named sqlite_settings.py
:
ROOT_PATH = os.path.dirname(__file__)
DATABASE_ENGINE = 'sqlite3'
DATABASE_NAME = os.path.join(ROOT_PATH, 'db.sqlite')
DATABASE_USER = ''
DATABASE_PASSWORD = ''
DATABASE_HOST = ''
DATABASE_PORT = ''
Finally, in your local_settings.py
you'd import
the pieces you wanted (as well as override what you
want to modify):
from site_caching_settings import *
from sqlite_settings import *
CACHE_BACKEND = "localmem:///"
You're Right. It doesn't scale.
I think the obvious weakness to this approach is that
it doesn't scale well, and it isn't a replacement for
the standard local_settings.py
trick, but it has
served me quite well for projects that only need to be
deployed in a small number of environments. For example,
work and personal projects that are not intended to be
reusable or pluggable apps.