Django Settings in Dev and Production: Why the hoops?

So, I’ve taken a break from active development on my project to take a step back and really get a good development workflow together. I’ve been fighting with various components of my development workflow, and in the end decided to compromise: I won’t have something that looks exactly like production, but I’ll have something that works and is easy to use. I’ll make up for it by having a staging environment on the same host as the production deployment, which will catch any differences between dev and production that result from my non-identical setup on my laptop.

In getting things going, one thing I ran into immediately was that things on my dev box are different from production: database credentials, paths to media, etc., and since I’m not using Apache and a reverse proxy some of the paths in settings.py will also be different. So what to do?

Turns out there’s an entire page on the Django wiki detailing the ways in which people keep their dev and production settings from trampling each other. There are also various blog posts where people have come up with interesting ways to make things work properly, usually by taking advantage of the fact that your app’s settings are just python code. As such, you can perform any valid Python wizardry you want to make the right things happen.

I don’t think there’s anything necessarily wrong with doing all of that stuff, but what I’m wondering is this: why not just tell your version control system of choice to *ignore* your settings.py file? This way, you can have a settings.py file on your dev box that works perfectly for your dev environment, and a separate one in production that works perfectly for that environment. Never the twain shall meet.

If you’re using one of the methods described on the Django site or any of the blog posts, what are you getting out of it that couldn’t be accomplished by ignoring settings.py? It just seems like it’s simpler and cleaner to do it that way, but I assume there’s some benefit to jumping through these hoops that I’m missing.

Input is hereby solicited. Please tweet/link/post this wherever, ‘cos I’d like some opinions on the matter.

  • http://sccs.swarthmore.edu/~cbr Jeff Kaufman

    If you leave settings.py out of version control, the downside is that settings.py will not be under version control. Simple. You can no longer compare versions, revert changes, or do any of the other nice things version control gives you.

  • http://www.gelens.org Jeffrey Gelens

    What I always do is splitting up settings.py in two files. One file contains the environment specific settings (like path, etc.), the other static stuff.

  • http://blog.amber.org/ petrilli

    The trick is to create a settings.py that’s under version control and at the end, a:

    try:
    from localsettings import *
    except:
    pass

    That way you can over-ride things and not put that file in the VCS.

  • http://www.mitechie.com Rick Harding

    The big one is getting new settings.py info into the live system. I’ve been bitten a pair of times where I added a new config var and pushed the changes requiring it up to the live server. Since I didn’t make a similar change to the live system, it borked. Doing things like adding a sample settings file and then keeping that in sync is just a pita as well.

  • Kevin Teague

    The settings.py contains application instance-specific configuration data. The Django tutorial creates a starter setting.py file inside your application code – but this is misleading, as putting instance-specific configuration into version control alongside the rest of your code makes no sense – this file will almost always contain hard-coding specific to a particular installation instance. Many have solved it with clever Python hackery, but that’s still a bass-ackward way of dealing with instance configuration. Instead, keep that file outside of the rest of your code, and either manually hand-manage it like you are doing, or use a lightweight instance-specific project in a vcs to manage specific instances if you need to keep the history of a specific install available. Then you can manage Django-based projects in the same manner as you’d manage any other application that needs instance-specific configuration.

  • http://intranation.com/ Bradley Wright

    What I do is use dynamic paths etc. for the settings.py, and then import all of it into production_settings.py and override what’s needed there. It works every time and has way more DRY love. Having an ignored local_settings seems like madness to me.

    Example here:
    http://github.com/bradleywright/django-layout/blob/26b579329068a34d82f65a698d0aacec750ce813/yoursite/settings.py

    (sorry for pimping my own Django thing)

  • Malcolm Tredinnick

    Most of the commenters are on the same path, but nobody’s said it explicitly: there are only a few pieces of the settings file that vary between production, development and staging/testing environments. All the rest are critical to the functionality of the collection of apps you’re building. So you want them to be identical between the two environments and part of the information you package and ship to your production environments.

  • m0j0

    Thanks, Malcolm. I was starting to form that thought from reading some other stuff, and the comments here. Thanks for presenting the completed version of the thought — well said. :)

  • m0j0

    So, I figured this out, along with a few other things — including the fact that I’m going to have to do the same type of “if-else” in my “myapp.wsgi” file. Hadn’t seen that discussed before, but I guess it’s not a given that everyone is using mod_wsgi either ;-)

  • http://www.a3-system.eu Thomas

    The problems are always the same :
    _ You want yr artifact to contain as few environment dependent variables as possible (preferably “None”).
    _ You want yr configs to support all the possible scenarii and be versionned.

    It is all possible with a decent VCS. Basically, you deployment on an environment needs to come from 2 (VCS) sources. In the case of Python it is weird as the code is yr artifact while in some other environments (java, C/C++, …) there is a generation step in between … but with a simple shell script, it is easy to fetch the data from 2 VCS and have them exported in the same location.

    The best is even to allow for Branching and use appropriately the authentication mechanism so that some one deploying in UAT/PROD/… has to provide his/her credential reminding him/her that he/she needs to “su” his/herself to do so