~ 2 min

Configuring django to support multiple environments

#django #settings.py

We've all faced a situation where we need to change some configuration inside our settings.py but only for a specific environment. If this happens on our own machine, we might be tempted to simply change it, knowing we cannot never commit it because it might cause problems. If you need to change a configuration for a remote server, then this won't work, and you need a proper solution.

There are a couple of ways to solve this:

  • You can create different settings.py for different environments, but don't do this!
  • You can create different config files per environment like settings.production.py and settings.development.py and then load them from settings.py. This is already better.
  • You can define all your variables inside a .env file. Create one per environment and load it from settings.py. This will also work but you'll need to manage your different .env files.
  • You can can load the information directly from environment variables (env vars).

I will go with the last one because it is the one more in line with the The twelve-factor app that says:

The twelve-factor app stores config in environment variables (often shortened to env vars or env). Env vars are easy to change between deploys without changing any code; unlike config files, there is little chance of them being checked into the code repo accidentally; and unlike custom config files, or other config mechanisms such as Java System Properties, they are a language- and OS-agnostic standard.

So, the most basic way to load a variable from the environment is using os.environ. Here's a basic example to load SECRET_KEY from an env var:

import os
SECRET_KEY = os.environ['SECRET_KEY']

This will throw an error if the env var is not defined which is fine in this case because you do not want your app to run without a defined SECRET_KEY. How about DEBUG? Defined or not, we could/should still run the app. We can consider it to be always false (as the default) and only make it to true once it's defined as an env var. This is how to do it:

import os
DEBUG = os.environ.get('DEBUG', 'False').lower() == 'true'

This will not crash due to the .get(), but you need to keep in mind that an env var is passed as a string. If you need anything other than a string, you'll need to convert is yourself. In this case, we get the DEBUG env var but get "False" if it's not defined. Once we have this and just to be safe, we lower case it because it might be written as "True", "TRuE", ... Finally, we can check if it's equal to "true" and in that case DEBUG is really defined as True.

This is a simple but effective technique that you can apply to any configuration inside settings.py to specify it per environment.

Subscribe to the newsletter

As a full-stack web developer I write about both the backend and frontend. If you liked what you read and want more, subscribe to my newsletter and I'll be sure to let you know once I release new articles.

I hope you like it! Share it with others who could enjoy it too.

Related posts

If you liked this post and want to read more, take a loot at these: