Open In App

How to Manage Local vs Production Settings in Django?

Last Updated : 17 Sep, 2024
Comments
Improve
Suggest changes
Like Article
Like
Report

When developing a Django application, managing settings for different environments (local development, testing, staging, and production) is crucial for ensuring smooth deployment and security. You don't want the same settings (like debug mode or database credentials) for local development and production. In this article, we’ll explore different strategies to manage local vs production settings in Django effectively.

Why Separate Local and Production Settings?

Local development environments and production environments serve different purposes:

  • Local (Development): Used for testing, debugging, and development purposes. Typically runs on your machine with the DEBUG mode on and has relaxed security measures.
  • Production: Hosts the live version of your site, usually with stricter security measures, error reporting, and optimized performance settings.

Keeping the settings separate helps ensure:

  1. Security: Sensitive information (like secret keys, database credentials) isn't exposed in the production environment.
  2. Performance: Different configurations for caching, databases, and static files are needed in production for optimal performance.
  3. Debugging: The DEBUG setting, which should be True in development, must always be False in production to prevent leaking sensitive information in error pages.

Common Differences Between Local and Production Settings

Here are a few key settings that differ between local and production environments:

  • DEBUG: Should be True locally but must be False in production.
  • SECRET_KEY: A unique secret key for each environment (avoid sharing the same key).
  • ALLOWED_HOSTS: In production, this should be set to your domain(s). Locally, it can be ['localhost', '127.0.0.1'].
  • DATABASES: You may use SQLite in local development and PostgreSQL, MySQL, or other databases in production.
  • STATIC and MEDIA Files: In production, you should configure a web server or storage service (like AWS S3) to serve static and media files.

Note: These all parameters are managed from the settings.py file.

Strategy 1: Using Multiple Settings Files

One of the most common ways to manage local vs production settings is by creating multiple settings files.

Create a settings directory

In your Django project, create a settings/ directory inside the main project directory.

myproject/
└── myproject/
└── settings/
├── __init__.py
├── base.py
├── local.py
└── production.py

Base Settings (base.py)

Start by creating a base.py file for settings that are common to both environments.

Python
# base.py

import os
from pathlib import Path

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

SECRET_KEY = 'your-default-secret-key'  # Placeholder

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    # Add your apps here
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'myproject.urls'

Local Settings (local.py)

In the local.py file, inherit from base.py and customize settings for development.

Python
# local.py

from .base import *

DEBUG = True

ALLOWED_HOSTS = ['localhost', '127.0.0.1']

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

STATIC_URL = '/static/'

Production Settings (production.py)

In the production.py file, inherit from base.py and override the necessary settings for production.

Python
# production.py

from .base import *

DEBUG = False

ALLOWED_HOSTS = ['yourdomain.com', 'www.yourdomain.com']

SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', 'your-production-secret-key')

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': os.environ.get('DB_NAME'),
        'USER': os.environ.get('DB_USER'),
        'PASSWORD': os.environ.get('DB_PASSWORD'),
        'HOST': os.environ.get('DB_HOST'),
        'PORT': os.environ.get('DB_PORT', '5432'),
    }
}

STATIC_ROOT = os.path.join(BASE_DIR, 'static/')
STATIC_URL = '/static/'

Modify __init__.py: Set a default settings file (like local.py) in the __init__.py file, or load environment-specific settings dynamically.

Python
import os

env = os.environ.get('DJANGO_ENV', 'local')

if env == 'production':
    from .production import *
else:
    from .local import *


Setting Environment Variables: In production, set the DJANGO_ENV environment variable to 'production':

export DJANGO_ENV=production

Running the Application: Django will now load the correct settings based on your environment variable.

Strategy 2: Using Environment Variables

Another approach is to manage sensitive and environment-specific settings using environment variables.

Use os.environ in Your Settings

In your settings.py, replace sensitive values with environment variables:

Python
import os
from pathlib import Path

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

SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', 'default-secret-key')

DEBUG = os.environ.get('DJANGO_DEBUG', 'True') == 'True'

ALLOWED_HOSTS = os.environ.get('DJANGO_ALLOWED_HOSTS', 'localhost').split(',')

DATABASES = {
    'default': {
        'ENGINE': os.environ.get('DJANGO_DB_ENGINE', 'django.db.backends.sqlite3'),
        'NAME': os.environ.get('DJANGO_DB_NAME', BASE_DIR / 'db.sqlite3'),
        'USER': os.environ.get('DJANGO_DB_USER', ''),
        'PASSWORD': os.environ.get('DJANGO_DB_PASSWORD', ''),
        'HOST': os.environ.get('DJANGO_DB_HOST', 'localhost'),
        'PORT': os.environ.get('DJANGO_DB_PORT', ''),
    }
}

Set Environment Variables

Set environment variables locally in your terminal:

export DJANGO_SECRET_KEY='your-secret-key'
export DJANGO_DEBUG=True
export DJANGO_ALLOWED_HOSTS='localhost,127.0.0.1'

In production, configure environment variables using your hosting provider or .env files for tools like Docker or Heroku.

Strategy 3: Using django-environ

The django-environ package is an excellent tool for managing environment variables in a more structured way. It allows you to store your configuration in .env files and load them into your Django settings.

Install django-environ:

pip install django-environ

Create a .env File

Add a .env file to the root of your project:

DJANGO_SECRET_KEY=your-secret-key
DJANGO_DEBUG=True
DJANGO_ALLOWED_HOSTS=localhost,127.0.0.1

Modify settings.py

Load environment variables in settings.py:

Python
import environ
import os

env = environ.Env(
    DEBUG=(bool, False)
)

environ.Env.read_env(os.path.join(BASE_DIR, '.env'))

SECRET_KEY = env('DJANGO_SECRET_KEY')
DEBUG = env('DJANGO_DEBUG')
ALLOWED_HOSTS = env.list('DJANGO_ALLOWED_HOSTS')

DATABASES = {
    'default': env.db(),
}

Conclusion

Managing local vs production settings in Django is crucial for developing secure, scalable applications. Whether you choose multiple settings files, environment variables, or a combination of both (using tools like django-environ), it’s important to keep your configurations modular, secure, and easy to maintain. By separating local and production settings, you can ensure your application behaves appropriately in different environments and stays secure during deployments.


Next Article
Practice Tags :

Similar Reads