Why apps have multiple settings files

Jacqueline Kazil
The coderSnorts
Published in
4 min readSep 14, 2015

Have you ever looked at a project and saw all sorts of settings files and wonder why there are so many — because this is not what you see in all the tutorials that you have been doing? While this can happen in any language or framework, this blog post is a walk-through for how these work in Django.

Let’s look at the code for the API for The Every Kid In A Park project built by the people at 18F. If you don’t know what an API is, no worries — you can read all about that here.

For the purposes of this post, what you should know is that this code base is a web application (or app), and the app has a folder of settings files, which can be found at `ekip-api/ekip/config/settings/`.

In this folder you will find the following files:

  • dev.py
  • production.py
  • test.py

As you can guess, each of these files support a different environment — test supports testing, production supports production, and dev support development.

You will also see a file called `base.py`. This is imported into all of the other files at the top of the file. If you preview dev.py, production.py, or test.py, you will see the following line:

from .base import *

If you don’t know Python, this is saying that from the base(.py) file, everything is imported. Then the rest of the file (dev, production, test) defines variables specific to the environment. In the case of Python, if the variable is defined twice, it is the second definition that wins.

When you set up your environment you would set your settings file to whatever you wanted to load. If you’re in development, you would set it to load dev.py.

At the bottom of dev and production, you will see the following:

try:
from .local_settings import *
except:
pass

This introduces the possibility of an additional file called local_settings.py, which would be located in the same folder. Having a try and except around the import allows it to fail silently — meaning the local_settings.py is not a required file.

So, why isn’t local_settings.py in the repository? Because this file is specific to the setup of the environment and it can be used for a variety of reasons. For example, it could be used to override some of the variables.

This is an example of how the settings work for the Every Kid in Park API app. The dev.py is the main file. That first imports base, then tries to import local_settings at the end.

To set this project up locally, you want to load the dev.py file as your settings, then add a local_settings.py file to override any settings.

A less complex example

Let’s take a look at another project that is in development — PyLadies DC Opportunities App. This project hasn’t grown to the same level of complexity as the previous project has.

You can find the settings file here. In this example, there is no base.py file. This is because the purpose of the base.py file in the previous example is being fulfilled by the settings.py file is this example. Below is a comparison of the files in a development settings.

The top row is how Every Kid in a Park is set up to inherit settings, while the bottom row is how the Opportunities app is set up.

Neither one is better than the other. The reason that the other project has a base.py file is because it is more complex and further along in development.

Once again, you have the local import at the bottom of the file.

try:
from settings_local import *
except:
pass

This currently serves one main purposes:

  1. To override the database settings, because we are moving from SQLite to Postgres.

For this app, you would want to create a file in the same directory that is called `settings_local.py` in this case. In the previous example, it was local_settings.py. This is just a matter of preference.

A sample local_settings.py file for this application would look like this:

DATABASES = {
‘default’: {
‘ENGINE’: ‘django.db.backends.postgresql_psycopg2’,
‘NAME’: ‘opportunities’,
‘USER’: ‘opps’,
‘PASSWORD’: ‘opps’,
‘HOST’: ‘localhost’,
‘PORT’: ‘5432’,
}
}

Normally, you don’t want to add these directly to the github repo, because you could accidentally then use them in production — that would make your app insecure, because anyone could take advantage of it with the secret key and the database information.

Final Steps to note: .gitignore and env variables

.gitignore. You don’t want to check in your local settings file, so you want to add it your .gitignore. Here is the line in the Opportunities project.

env variables. In these settings files, you will notice the following:

 os.environ.get(SOMETHING, DEFAULT_TO_THIS)

The settings files look for environmental variables that are set at the OS level. Meeting if you were on the command line, you could run the following and it would tell you what the variable was equal to. (The dollar sign before the variable name is important otherwise it will literally echo ‘SOMETHING’.)

echo $SOMETHING

It is through the env variables that you would set up your application when you get to a production settings.

Do I need multiple settings files?

Yes, if you have default settings that you want others on you team to have access to and they are not sensitive.

No, if all your settings are the same through all your environments. Often there is a local settings file that still exists to override the default.

I hope this helps you to better understand why there might be multiple settings files for project!

--

--

Jacqueline Kazil
The coderSnorts

Data science, complexity, networks, rescued pups | @InnovFellows, @ThePSF, @ByteBackDC, @Pyladies, @WomenDataSci, creator of Mesa ABM lib