Django Settings for Multiple Environments

Separate settings for dev and prod in a single django project


Update July 2019: I can confirm this tutorial still works great with the latest version of Django 2.

When working by yourself, on a single server, it's easy to simply change the django settings when you deploy to your server. But what about working on a larger team, or running your project in multiple environments (for instance: local machine, dev, qa, staging, production)? Settings management can become a nightmare in cases like these when trying to work with a single settings file. There is a better way — using multiple settings files! Remember, django is just python, and you can pretty much do anything in python. So let's dive right into it.

Create Separate Settings Files

Django gives you the ability to specify which settings file to use when running your development server as such:

$ ./manage.py runserver --settings=myproject.settings

This is sort of the default behavior, and will run your project with the usual settings file located at myproject/settings.py.

Now I can create two separate settings files, one for my local environment, using sqlite, and one for my server environment using mysql.

File: myproject/settings/dev.py

DEBUG = True
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'db.sqlite3',
        'USER': '',
    }
}

File: myproject/settings/prod.py

DEBUG = False
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'myproject',
        'USER': 'myuser',
        'PASSWORD': 'bestpasswordever',
    }
}

And now, I can simply choose which settings file to use when running my development server as such:

$ ./manage.py runserver --settings=myproject.settings.dev
$ ./manage.py runserver --settings=myproject.settings.prod

Share Common Settings Between Both

Having separate files is a huge first step, but what about all those settings that are global between every environment? Such as INSTALLED_APPS or many of the other required Django settings. Let's create a shared settings file called base.py.

File: myproject/settings/base.py

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'polls',
    'myapp',
)
# Other Django settings here
# ...

Now in my dev.py and prod.py settings files, I'll import my common settings from base.py.

File: myproject/settings/dev.py

from myproject.settings.base import *
DEBUG = True
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': 'db.sqlite3',
        'USER': '',
    }
}

File: myproject/settings/prod.py

from myproject.settings.base import *
DEBUG = False
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'myproject',
        'USER': 'myuser',
        'PASSWORD': 'bestpasswordever',
    }
}

Any settings in your dev.py or prod.py settings files will override what's in base.py. Sweet!

Specifying Settings on the Server

Using the --settings option works great for the local development server, but how can you accomplish this on a "real" web server running your project? The answer lies in the WSGI file. Modify DJANGO_SETTINGS_MODULE environment variable, or fallback value to point to your appropriate settings file.

File: myproject/wsgi.py

import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myproject.settings.prod")

from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()

And there you have it!