Django
local settings
production settings
configuration management
environment variables

How to manage local vs production settings in Django?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Django settings should differ between local development and production, but the differences need to stay controlled and predictable. The safest pattern is to keep shared defaults in one base settings module, load environment-specific values from separate files or environment variables, and never hardcode secrets or deployment-only behavior into the development setup.

Split Shared and Environment-Specific Settings

A common project structure is:

text
1project/
2  settings/
3    __init__.py
4    base.py
5    local.py
6    production.py

base.py contains settings shared by every environment, while local.py and production.py override only what differs.

Example base.py:

python
1from pathlib import Path
2
3BASE_DIR = Path(__file__).resolve().parent.parent.parent
4
5INSTALLED_APPS = [
6    "django.contrib.admin",
7    "django.contrib.auth",
8    "django.contrib.contenttypes",
9    "django.contrib.sessions",
10    "django.contrib.messages",
11    "django.contrib.staticfiles",
12]
13
14MIDDLEWARE = [
15    "django.middleware.security.SecurityMiddleware",
16    "django.contrib.sessions.middleware.SessionMiddleware",
17    "django.middleware.common.CommonMiddleware",
18]

This keeps the common baseline in one place.

Override Only What Really Changes

Local development and production usually differ in a few predictable areas:

  • 'DEBUG'
  • database connection
  • allowed hosts
  • static/media storage
  • secret values
  • logging verbosity

Example local.py:

python
1from .base import *
2
3DEBUG = True
4ALLOWED_HOSTS = []
5
6DATABASES = {
7    "default": {
8        "ENGINE": "django.db.backends.sqlite3",
9        "NAME": BASE_DIR / "db.sqlite3",
10    }
11}

Example production.py:

python
1from .base import *
2import os
3
4DEBUG = False
5ALLOWED_HOSTS = ["example.com"]
6
7DATABASES = {
8    "default": {
9        "ENGINE": "django.db.backends.postgresql",
10        "NAME": os.environ["DB_NAME"],
11        "USER": os.environ["DB_USER"],
12        "PASSWORD": os.environ["DB_PASSWORD"],
13        "HOST": os.environ["DB_HOST"],
14        "PORT": os.environ.get("DB_PORT", "5432"),
15    }
16}

Notice that production values come from environment variables rather than from committed source.

Select the Settings Module Explicitly

Django chooses its settings module from DJANGO_SETTINGS_MODULE. That means each environment should start the app with the right module name.

bash
export DJANGO_SETTINGS_MODULE=project.settings.local
python manage.py runserver

For production:

bash
export DJANGO_SETTINGS_MODULE=project.settings.production
python manage.py migrate

Being explicit here prevents a large class of deployment mistakes.

Keep Secrets Out of Version Control

Secret keys, database passwords, API tokens, and similar values should not live in committed settings files. Use environment variables or a secrets manager instead.

A simple example:

python
import os

SECRET_KEY = os.environ["DJANGO_SECRET_KEY"]

This is safer and also makes deployment automation easier because credentials can change without changing source files.

Use Packages Only When They Simplify the Setup

Libraries such as django-environ can make environment variable parsing more convenient, but they are helpful only if they actually simplify the project. The core design principle remains the same with or without a helper package: shared defaults in one place, environment-specific overrides elsewhere, secrets outside source control.

Avoid Big Divergence Between Environments

Local and production should differ where necessary, but not in arbitrary ways. If the local stack uses SQLite and production uses PostgreSQL, that may be acceptable for a small project, but it can also hide database-specific behavior until deployment.

The more your environments diverge, the more surprises you invite. Use lightweight differences for convenience, but keep important behavior aligned whenever possible.

Common Pitfalls

  • Keeping all settings in one file and scattering if DEBUG logic everywhere.
  • Committing secrets into source-controlled settings files.
  • Forgetting to set DJANGO_SETTINGS_MODULE correctly in deployment.
  • Letting local and production databases behave too differently without realizing the tradeoff.
  • Duplicating large blocks of settings instead of inheriting from a shared base.

Summary

  • Put shared Django settings in a base module and environment-specific overrides in separate files.
  • Use environment variables for secrets and deployment-specific values.
  • Select the correct settings module explicitly with DJANGO_SETTINGS_MODULE.
  • Override only what really differs between local and production.
  • Keep the environments aligned enough that deployment behavior does not become a surprise.

Course illustration
Course illustration