The Multiple Settings Files Pattern

Hernán Tylim
Django Musings
Published in
2 min readApr 18, 2016

I read this first in Two Scoops of Django a while back.

When we start working with Django we learn fast that we’ll need to use some settings values to run the app in development mode, and some other setting values for when we deploy the app in production.

What can we do to manage multiple setting scenarios in a way that it is neatly organized and keep everything versioned?

Meet The Multiple Settings Files pattern

After we create our django project we end up with a directory like this:

\manage.py
\app_name\_init_.py
\app_name\settings.py
\app_name\admin.py
\app_name\urls.py
\app_name\wsgi.py
...

With settings.py our settings module and where all django default configuration is.

Move settings.py file into a ‘ settings’ package and rename to (for example) base.py:

So you should end up with something like this:

\manage.py
\proj_name\_init_.py
\proj_name\settings\_init_.py
\proj_name\settings\base.py # all common settings
\proj_name\settings\local.py # local deployment only settings
\proj_name\settings\production.py # production only settings
\proj_name\settings\test.py # test only settings
\proj_name\admin.py
\proj_name\urls.py
\proj_name\wsgi.py

I’ll explain in a second the local.py, production.py and test.py files. But for now understand that they will be our new configuration files and we are going to tell Django which one to use with the DJANGO_SETTINGS_MODULE environment variable.

So while on production you will have to have add this environment variable declaration:

set DJANGO_SETTINGS_MODULE=proj_name.settings.production

and while on testing:

set DJANGO_SETTINGS_MODULE=proj_name.settings.test

and you get the idea.

But what about the new files.

If you remember you have all your original settings in base.py file, what you need to do now is to create empty production.py, local.py and test.py files and import base.py in them and override only what you need.

Example:

# settings/production.pyfrom .base import *# Everything from base is here, we overwrite only what we need:DEBUG=False
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': get_env_variable('DB_NAME'),
'USER': get_env_variable('DB_USER'),
'PASSWORD': get_env_variable('DB_PASS'),
'HOST': 'localhost',
'PORT': '',
}
}
...

Example:

# settings/local.pyfrom .base import *# Everything from base is here, we overwrite only what we need:DEBUG=True
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
...

And voila.

--

--