Skip to content

Django Settings Best Practice: Splitting base, local, and production Configs

A single settings.py creates real problems in production. The solution is a settings package — three files, clean separation, zero hacks. Here is exactly how to set it up.

MI

mubashar

· 2 min read
Share

The default Django project gives you a single settings.py file. This works fine for a tutorial but creates real problems in production: you end up with hardcoded secrets, DEBUG = True accidentally shipped, or hacky if 'PRODUCTION' in os.environ blocks everywhere. The solution is a settings package — three files, clean separation, zero hacks.

The problem with one settings file

A single settings file tries to be everything to everyone. You need DEBUG = True locally but False in production. You need an SQLite database for development but PostgreSQL in production. You need console email output locally but real SMTP credentials in production. Handling all of this in one file means either hardcoding values, using fragile environment detection, or — worst of all — accidentally deploying development settings.

The settings package structure

myproject/
  settings/
    __init__.py    # empty
    base.py        # shared by all environments
    local.py       # local development
    production.py  # production server

Delete your old settings.py — it conflicts with the new package.

base.py — the shared foundation

base.py contains everything that does not change between environments:

from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent.parent

INSTALLED_APPS = [
    # Django core apps ...
    # Your apps ...
]

MIDDLEWARE = [ ... ]
TEMPLATES = [ ... ]
ROOT_URLCONF = 'myproject.urls'

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}

STATIC_URL = '/static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'
MEDIA_URL = '/media/'
MEDIA_ROOT = BASE_DIR / 'media'
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

Note that SECRET_KEY, DEBUG, and ALLOWED_HOSTS are intentionally not in base.py. They belong in the environment-specific files.

local.py — development settings

from .base import *

DEBUG = True
SECRET_KEY = 'django-insecure-dev-only-key-change-this'
ALLOWED_HOSTS = ['localhost', '127.0.0.1']
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'

production.py — production settings

import os
from .base import *

DEBUG = False
SECRET_KEY = os.environ['SECRET_KEY']
ALLOWED_HOSTS = ['yourdomain.com', 'www.yourdomain.com']

SECURE_SSL_REDIRECT = True
SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')
SESSION_COOKIE_SECURE = True
CSRF_COOKIE_SECURE = True
SECURE_HSTS_SECONDS = 31536000
SECURE_HSTS_INCLUDE_SUBDOMAINS = True
SECURE_HSTS_PRELOAD = True

EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'
EMAIL_HOST = os.environ.get('EMAIL_HOST', '')
EMAIL_HOST_USER = os.environ.get('EMAIL_HOST_USER', '')
EMAIL_HOST_PASSWORD = os.environ.get('EMAIL_HOST_PASSWORD', '')

Pointing manage.py and wsgi.py at the right settings

In manage.py:

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings.local')

In wsgi.py and asgi.py:

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings.production')

On your production server, set DJANGO_SETTINGS_MODULE=myproject.settings.production and SECRET_KEY=... as real environment variables (in a .env file loaded by systemd, or via your hosting platform's secrets manager).

Running with a specific settings file

# Development (default via manage.py)
python manage.py runserver

# Explicitly override
python manage.py runserver --settings=myproject.settings.local

# Production check
python manage.py check --settings=myproject.settings.production --deploy

This structure has zero boilerplate and makes it impossible to accidentally ship DEBUG = True. Once you use it, you will never go back to a single settings file.

MI

Written by

Mubashar Iqbal

Web developer, SEO expert, and independent maker. I build products, write about what I've learned, and create free tools for developers and marketers.