How to Split Your Django Project Settings

Published: 11 months ago - Updated: 11 months ago

5 minutes - 996 Words

article 'How to Split Your Django Project Settings' banner

Summary

Learn how to modularize your Django project settings file to support multiple environments with ease.

Open Source Example

Related Articles

  1. Automatically Generate ERD of Your Django Models
  2. How to Setup Vite Js With Django 4.x

Introduction

In this blog post, You will learn how to modularize your Django project settings file to make it easier to support multiple environments such as local and production. We’ll also learn how to switch between these settings files easily based on env variable.

In a Django project, we typically have one settings file for local and production environments but it is not ideal to use one settings for both of those environment because these environments have different requirements and configurations.

The local environment is where we develop and test our code. It usually runs on our local machine and has different settings compared to the production environment. For example, we might use a different database or debugging tools (django-debug-toolbar , nplusone ) to make it easier to develop and test our code.

On the other hand, the production environment is where our code is deployed and used by real users. It requires more security, stability than the local environment. We might use different settings for the database, caching, logging, and other services to ensure that our application runs smoothly and securely.

By having different settings for local and production environments, we can ensure that our code works well in both scenarios and avoid any unexpected issues when we deploy our code to production.

Create Django project

In this article I will start with a fresh Django install but you can apply this steps in an existing project as well without any major changes.

# Create new django project
django-admin startproject mysite

# Create a virtual environment
virtualenv .venv

# Activate the virtual environment
source .venv/bin/activate # Linux
.venv/scripts/activate # Windows

# Install Django in virtual environment
pip install django

This will create the bellow files and directories.

📦mysite
 ┣ 📜__init__.py
 ┣ 📜asgi.py
 ┣ 📜settings.py
 ┣ 📜urls.py
 ┗ 📜wsgi.py

We only have one settings file for our production and local environment.

Let’s Start

  • Create a folder called settings in mysite directory
  • rename settings.py to base.py and move it to settings folder

Create the bellow three files in the settings folder

  • __init__.py
  • local.py
  • production.py

We will have the bellow folder structure.

📦...
 ┣
📦mysite
 ┣ 📂settings
 ┃ ┣ 📜__init__.py
 ┃ ┣ 📜base.py
 ┃ ┣ 📜local.py
 ┃ ┗ 📜production.py
 ┣ 📜__init__.py
 ┣ 📜asgi.py
 ┣ 📜urls.py
 ┗ 📜wsgi.py
📦...
 ┣

In the local.py file import the base settings and add the settings that are specific to our local environment.

from .base import *

LOCAL_INSTALLED_APPS = [
    "debug_toolbar",
]

# Concatinate the local apps to the installed apps list of our base settings
INSTALLED_APPS = INSTALLED_APPS + LOCAL_INSTALLED_APPS

DATABASES = {
    "sqlite": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": BASE_DIR / "db.sqlite3",
    },
}

In the above file we have created a new list of installed apps and concatenate the LOCAL_INSTALLED_APPS to the INSTALLED_APPS list of our base settings.

The same way you can append or remove any settings of our app according to our environment needs.

For example:

In the production.py we want to use MySQL so we overwrite the default database in our production settings.

from .base import *

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.mysql",
        "NAME": env("DB_NAME", default="test"),
        "USER": env("DB_USER", default="root"),
        "PASSWORD": env("DB_PASSWORD", default=""),
        "HOST": env("DB_HOST", default="localhost"),
        "PORT": env("DB_PORT", default="3306"),
        "OPTIONS": {"charset": "utf8mb4"},
    },
}

Setup .env

Next, we’ll set up our local environment variables. We use django-environ to help with this. It reads environment variables located in a file named .env in the top level directory of the project. The only variable we need to start with is DJANGO_SETTINGS_MODULE:

pip install django-environ

# create .env file
touch .env

Add the bellow variable in our .env file

DJANGO_SETTINGS_MODULE = "mysite.settings.local"

Read .env in base.py

Read the env file in our base settings file

# base.py

import environ

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent.parent

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

Since we moved the settings file inside a folder we need to add one more .parent to the BASE_DIR

BASE_DIR = Path(**file**).resolve().parent.parent.parent

Specify which settings file (local or production) you want to use.

mysite/settings/base.py

# base.py
DJANGO_SETTINGS_MODULE = env("DJANGO_SETTINGS_MODULE", default="mysite.settings.local")

Now we tell our app to use our specified Setting Modules in the manage.py file at the root of the project.

import DJANGO_SETTINGS_MODULE environment from base settings file

# manage.py 
from core.settings.base import DJANGO_SETTINGS_MODULE

The final manage.py will look something like this

manage.py

#!/usr/bin/env python
"""Django's command-line utility for administrative tasks."""
import os
import sys

from core.settings.base import DJANGO_SETTINGS_MODULE

def main():
    """Run administrative tasks."""
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings.local')
    try:
        from django.core.management import execute_from_command_line
    except ImportError as exc:
        raise ImportError(
            "Couldn't import Django. Are you sure it's installed and "
            "available on your PYTHONPATH environment variable? Did you "
            "forget to activate a virtual environment?"
        ) from exc
    execute_from_command_line(sys.argv)

if __name__ == '__main__':
    main()

Now when we start the development server, Django will use our specified settings file.

❯ pm runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
July 31, 2023 - 09:53:26
Django version 4.2.2, using settings 'mysite.settings.local'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Add Comment

Conversations (0)

Sign up for our newsletter

Stay up to date with the latest news and articles.