Using multiple in your Django project

Posted on Mon 07 October 2019 in Python • 4 min read

After going through "Django for professionals" and building the project in there, I started to build a Django project template based on what I learned from the book. The book goes through a development version of the project, and a production version, and it also makes use of Docker to run the web server and PostgreSQL server.

I realized it would be very useful to have one settings file for development and one for production. For example, in development I might not want to send emails via a SMTP service but just print the mail to the console, and in production there would be security settings which would be impractical in development.

Another thing I wanted to accomplish was to hide away certain variable (like SECRET_KEY and any passwords) so they wouldn't be pushed to GitHub.

In this article I'll explain how I set up all those things in my Django project template. You can also find the full code in my Django template repo. It might be useful to use that as a reference when going though this article.

Project structure

After creating a Django project there is one in the project folder. To split up the settings I start by creating a new folder (called settings) under the projects folder and add an file within it. I move the original file into the settings folder and rename it to This file will hold the settings that are common for both development and production.

Django project structure image

I then create a and a for the settings that will differ between the environments.

The setting files

At the top of each of these files I import the settings from

from .base import *

Then it is just a matter of moving the settings from that would differ from the different environments. For example this is how my looks like:

from .base import *

DEBUG = True



EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

    'JQUERY_URL': '',

# Django-debug-toolbar
import socket
hostname, _, ips = socket.gethostbyname_ex(socket.gethostname())
INTERNAL_IPS = [ip[:-1] + "1" for ip in ips]

Running the server

To start the Django server with a specific settings file run the following command:

python runserver --settings=project.settings.development

Lift out "secret" variables from the settings

Certain variables in the setting files is not something you'd want to publish on GitHub (or similar). For example the SECRET_KEY or any password to other services.

What I did here was to create an .env in the root of the project to put those variables into. For example:


In I then read the parameters from the .env file with os.environ.get().

SECRET_KEY = os.environ.get('SECRET_KEY')

If you're not using Docker to develop your Django app, this might be almost all you need.


One more thing is needed though. I found this out the hard way. Everything worked fine for me with the different setting files until I wanted to do a migration. Then I got a strange error that the SECRET_KEY value was empty. After lots of troubleshooting I found out that the still tried to read from the original

So this line in

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')

Needs to be updated to:

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings.base')

Docker compose

Since the runserver command will have a different parameter depending on if you want to run it with development settings or with production settings, I also split up the docker-compose.yml into two different files. The only difference between these two at the moment is the parameters of the runserver command.

You can run a specific docker compose file like this:

docker-compose -f docker-compose-dev.yml up -d

Now this can be pretty tiresome to type every time, especially if you need to do a exec web or look at the logs in your container etc. So on top of all this, I put common commands that I use with docker compose into a Makefile.

(Note also that I read in the .env file withing my docker compose files)


In the Makefile I construct different common commands. Like:

  • Looking at the logs in the container
  • Shut down the container
  • Execute a command within the container

Here is an excerpt of my Makefile:

    @docker-compose \
        -f docker-compose-dev.yml \
        down && \
        docker-compose \
            -f docker-compose-dev.yml \
            up -d

    @docker-compose \
        -f docker-compose-dev.yml \
        down && \
        docker-compose \
            -f docker-compose-dev.yml \
            up -d --build

    @docker-compose -f docker-compose-dev.yml logs

    @docker-compose -f docker-compose-dev.yml down

    @docker-compose -f docker-compose-dev.yml exec web $(cmd)

So to spin up my development environment I just run:

make dev

To look at the logs while the container is running:

make dev_logs


This is one way to use multiple setting files in you Django project. I also showed you how using these in a Docker scenario can be made easier with different docker-compose.yml and a Makefile to make the commands needed to be much shorter.

Let me know on Twitter if I can improve this article, or if you have other resources to help out with understanding this topic.