Multiple Settings Files
Split settings into base, dev, staging, and prod. Learn import patterns, SECRET_KEY handling, debug flags, database overrides, and how to run with --settings or environment variables.
1. Introduction
A single settings.py file works fine when you are learning, but real projects need different configurations for different environments. Your development machine needs DEBUG = True and a local database. Your production server needs DEBUG = False, a real database, and secure keys loaded from environment variables.
The standard solution is to split your settings into multiple files — a base file with shared settings, and separate files for each environment that extend it.
- You should already have
myprojectset up with a workingmysite/settings.py. - Your
.venvmust be active and Django 5.2 installed.
2. The problem with one settings file
With a single settings file, developers often end up doing one of these:
- Manually changing
DEBUGand database settings before deploying — and forgetting to change them back. - Committing
SECRET_KEYand database passwords to Git. - Using
ifstatements insidesettings.pyto switch between environments — which gets messy fast.
3. The settings folder structure
Instead of a single settings.py file, we create a settings/ folder inside mysite with separate files for each environment:
myproject/
├── .venv/
├── manage.py
├── requirements.txt
└── mysite/
├── __init__.py
├── urls.py
├── asgi.py
├── wsgi.py
└── settings/
├── __init__.py
├── base.py
├── dev.py
└── prod.py
base.py— shared settings that apply to all environments.dev.py— development-specific settings that override or extend base.prod.py— production-specific settings that override or extend base.
4. Set it up step by step
Step 1 — Create the settings folder
mkdir mysite/settings
touch mysite/settings/__init__.py
Step 2 — Move and rename settings.py to base.py
mv mysite/settings.py mysite/settings/base.py
Step 3 — Create dev.py
dev.py imports everything from base.py and overrides what needs to be different in development:
# mysite/settings/dev.py
from .base import *
DEBUG = True
ALLOWED_HOSTS = ['127.0.0.1', 'localhost']
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}
Step 4 — Create prod.py
prod.py also imports from base.py but uses stricter settings for production:
# mysite/settings/prod.py
from .base import *
import os
DEBUG = False
SECRET_KEY = os.environ['SECRET_KEY']
ALLOWED_HOSTS = ['yourdomain.com', 'www.yourdomain.com']
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': os.environ['DB_NAME'],
'USER': os.environ['DB_USER'],
'PASSWORD': os.environ['DB_PASSWORD'],
'HOST': os.environ['DB_HOST'],
'PORT': os.environ.get('DB_PORT', '5432'),
}
}
os.environ in detail in the next tutorial. For now, understand that sensitive values like passwords and keys should never be hardcoded — they should be loaded from the environment.
5. Tell Django which settings file to use
You need to update manage.py and mysite/wsgi.py to point to the new settings location.
Update manage.py
# manage.py
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings.dev')
Update wsgi.py
# mysite/wsgi.py
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings.prod')
Alternatively, you can pass the settings file directly when running a command:
# Use dev settings
python manage.py runserver --settings=mysite.settings.dev
# Use prod settings
python manage.py check --settings=mysite.settings.prod
settings.py to settings/base.py, run python manage.py check to confirm Django can still find the settings and everything is working correctly.
6. What stays in base.py
base.py should only contain settings that are the same across all environments. A good rule: if a value changes between dev and prod, it does not belong in base.py.
Stays in base.py:
BASE_DIRINSTALLED_APPSMIDDLEWARETEMPLATESAUTH_PASSWORD_VALIDATORSLANGUAGE_CODE,TIME_ZONE,USE_TZ
Moves to dev.py or prod.py:
DEBUGSECRET_KEYALLOWED_HOSTSDATABASES
7. Next steps
Your settings are now split cleanly across environments. The next step is to load sensitive values like SECRET_KEY and database passwords from environment variables so they never end up in your codebase or Git history.