Blog Tags: 

Django for development and production

So you developed a Django web application and now need to deploy it into production, but still need to actively continue development (bugfixes, tweaks, adding and testing new features, etc.)

In your development environment you probably had debugging enabled, performance settings disabled, used SQLite as your database, and other settings that make development easier and faster. 

But in production you need to disable debugging, enable performance, and use a real database such as MySQL or PostgreSQL, etc.

Hopefully, your development environment can simulate your production environment as well, sort of staging, so your final tests prior to deployment provides the smallest delta.

  • Sometimes you need to emulate the full production environment.
  • Sometimes you need to emulate the full development environment.
  • Sometimes a mixture of the two.

This leads to the question, how do you seamlessly manage your development and production settings without adding overhead?

It turns out there is quite a lot of discussion on how to setup Django that supports both a development and production environment, for example:

  • Completely different files (usually you configure the webserver to add the production settings to the python path, and use the default (development) settings when using the dev webserver.
  • By hostname
  • By variable (PRODUCTION = True)

We recently came across this issue when we were ready to deploy the TurnKey Hub into production.

I didn't really like the above mentioned solutions, so this is what I came up with:

  • (full settings for production)
  • (override production for full development)

If the environment variable DEVELOPMENT is set, use settings-dev to override the production settings.

I was toying with the idea to have full control over the settings via the environment, for maximum flexibility, but in the end decided against it, as it added too much complexity with not enough gain.

Our looks something like this:

DEBUG = True


DATABASE_NAME = '/tmp/dev.db'

The (full settings for production) includes the following snippet at the end.
if os.environ.get('DEVELOPMENT', None):
    from settings_dev import *
You can get future posts delivered by email or good old-fashioned RSS.
TurnKey also has a presence on Google+, Twitter and Facebook.


Martin Lundberg's picture

The problem with that solution if I understand it correctly is that in the dev config file you don't have access to the already set settings so if you for example wan't to add an application to the installed_apps setting you need to add all of the ones that are in the production settings file.

If you instead write your (production) as normal and then in the do from settings import * you can do things like:

Than all you have to do is make sure the dev server loads the dev config file.
Alon Swartz's picture

I've found debug_toolbar is really useful when optimizing my application, but is very annoying when doing regular development. Not only because the application is less responsive, but because it encourages premature optimization (which is the root of all evil).

So, for this edge case, I usually add debug_toolbar manually during the optimization phase.

With regards to your suggestion, it results in circular imports (though it should work) - for example:
print "this is foo"
from bar import *
print "this is foobar: %s" % FOOBAR
from foo import *
print "this is bar"

When we execute, this is what happens:

$ python
this is foo
this is foo
this is foobar: foo
this is bar
this is foobar: bar

Guest's picture

No, there aren't any circular imports; I think Martin Lundberg is talking about doing it like this:

Phil's picture

normally as developer you use a version control system. so i use git and have a devel branch where new changes will be committed into. if the devel version seems to be stable i merge the devel branch into the productive and git handles the changes at the

sometimes git displays some conflicts, but these are corrected quickly

Alon Swartz's picture

Using revision control is a must - I love git, I'm addicted, can't live without it.

But, I don't follow how you use git to achieve what the article is trying to explain:

In your development environment you probably had debugging enabled, performance settings disabled, used SQLite as your database, and other settings that make development easier and faster. 

But in production you need to disable debugging, enable performance, and use a real database such as MySQL or PostgreSQL, etc.

Do you update your file every time you need to fix a bug, tweak something, or add a new feature? This seems awfully repetitive and error prone...

Seth Gottlieb's picture

I take a similar approach of an override at the bottom of the file but instead of checking an environment variable I try to import settings_dev 

	from settings_dev import *
except ImportError, exp:

I have ignored in source control but I do have a settings_dev.sample checked in for when I have other developers working with me.  

Bnvnsn's picture

I would consider the same theory, but opposite practice: have your dev settings in, then have on your production boxes and have try to read settings_prod. This means if your code is installed onto a dev box, the default configuration is to not read live settings. (With a dev DB/prod DB setup, you would not want production DB read by default.)

Tomas's picture


Thanks for sharing.

I use similar approach. I have file called which is my development settings. is imported in Then I have bunch of other settings files -, etc. Where sandbox is my test environment, prod is production etc.

I use fabric to deploy my applications to different environments. File is renamed to when I deploy to sandbox server.

Works for me.

JimDD's picture

This was discussed on StackOverflow, there's a few good tips there.

Rock's picture

I use Lincoln Loop's django-startproject. It includes a customized version of that looks for a "local" and loads that if it is present in the "conf/local" directory. Otherwise it falls back to loading the in the "conf" directory. The version of in "conf/local" can be complete unto itself, but more typically it imports the main from the "conf" directory and then overrides and/or extends those settings as necessary.

The in the "conf" directory should be version controlled, however the version in "conf/local" should not. (There is a subdirectory called "conf/local/example" and it iis a good place to put varioius examples of different useful local files and these can be version controlled.)

By the way, django-startproject extends this same concept to also support custom management. While not perfect, the only serious problem I have found with django-startproject is that experienced django programmers tend to grumble for a few days while they get used to it.

Joseph Edwards's picture

Add `` to the `.gitignore`.

Next, move all the settings that are common to both dev and production to a file named `` or the like. This one is version-controlled because it's the same all the time (common installed apps, common settings).

Then, create two `` files - one for dev (i.e., `debug=true`, uses SQLite, etc.) and one for production. In both files, do `from settings_core import *`.

(I know `from... import *` is generally frowned upon, but alt is either: (a) `import settings_core as sc` and referencing `sc.SETTING`, or (b) `from settings_core import SETTING1, SETTING2, ... SETTINGX`. I think of it as sourcing the core common settings, a'la shell scripting.)

This way, one can, i.e., add to the apps list but keep `STATIC_ROOT` separate, and other nifty configs.

BarneyJ's picture

Here is some more info about that . Really informative articles!


Post new comment