Django Settings Best Practices

  1. Install decouple module to get system variables.
pip install python-decouple
  1. Inside Django project directory, create settings directory and move settings.py file inside it.
  2. inside newly created settings directory create __init__.py, base.py, development.py, and production.py files.
  3. Inside __init__.py file add the following:
# Load module based on `.env` variable.
# this code mimmics `from module import *` with `module` being `SETTINGS_ENVIRONMENT` variable
from importlib import import_module

from decouple import config

module_name = config("SETTINGS_ENVIRONMENT", ".development")
module = import_module(module_name)
module_dict = module.__dict__
try:
	to_import = module.__all__
except AttributeError:
	to_import = [name for name in module_dict if not name.startswith("_")]
globals().update({name: module_dict[name] for name in to_import})
  1. inside base.py file add following code as well as all global settings.
# This file contains project settings shared by all environments(I.e. production, development, ...)
# This file inherits default `settings.py` which is normally untouched. all new project settings are applied here.
import os
from decouple import config
from .settings import *  # Default and untuched django settings file
BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))

# Secret Key
SECRET_KEY = config("SECRET_KEY")

# Application definition
INSTALLED_APPS += [
   # requirements
   # Applications
]

MIDDLEWARE += [
	# Required middlewares
]
  
TEMPLATES = [
	{
		"BACKEND": "django.template.backends.django.DjangoTemplates",
		"DIRS": [
			os.path.join(BASE_DIR, "project", "templates"),
			os.path.join(BASE_DIR, "APP", "templates"),
		],
		"APP_DIRS": True,
		"OPTIONS": {
			"context_processors": [
				"django.template.context_processors.debug",
				"django.template.context_processors.media",
				"django.template.context_processors.request",
				"django.contrib.auth.context_processors.auth",
				"django.contrib.messages.context_processors.messages",
			],
			"debug": True,
		},
	},
]

DATABASES = {
	"default": {
		"ENGINE": config("DB_ENGINE", default="django.db.backends.postgresql_psycopg2"),
		"NAME": config("DB_NAME", default="database"),
		"USER": config("DB_USER", default="postgres"),
		"PASSWORD": config("DB_PASSWORD", default="root"),
		"HOST": config("DB_HOST", default="localhost"),
		"PORT": config("DB_PORT", default="5432"),
	}
}

# Rest Framework
REST_FRAMEWORK = {
	"DEFAULT_FILTER_BACKENDS": ["django_filters.rest_framework.DjangoFilterBackend"],
	"DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.NamespaceVersioning",
	"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.PageNumberPagination",
	"PAGE_SIZE": 20,
}

# Email options
EMAIL_FORMAT_HTML = True  # if false plain text emails will be sent

# Static files (CSS, JavaScript, Images)
STATIC_URL = "/static/"
STATIC_ROOT = os.path.join(BASE_DIR, "project", "static_root")
STATICFILES_DIRS = (
	os.path.join(BASE_DIR, "project", "static"),
	os.path.join(BASE_DIR, "APP", "static"),
)

# Media Files
MEDIA_URL = "files/"
MEDIA_ROOT = os.path.join(BASE_DIR, "project", "media")

# allows to load iframe from same hostname
X_FRAME_OPTIONS = "SAMEORIGIN"

# extend upload
DATA_UPLOAD_MAX_NUMBER_FIELDS = 10000

💡 Change os.path.join(BASE_DIR, "APP", "templates"), line with suitable lines to import your templates.
💡 Change os.path.join(BASE_DIR, "APP", "static"), line with suitable lines to register static file's directory.

  1. inside development.py file add following:
from .base import *

ALLOWED_HOSTS = ["127.0.0.1", "localhost"]

# Email Testing using file logs
EMAIL_BACKEND = "django.core.mail.backends.filebased.EmailBackend"
EMAIL_FILE_PATH = os.path.join(BASE_DIR, "emails")

# debug for "sorl.thumbnail"
THUMBNAIL_DEBUG = True

# Allow Jupiter to show results
os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"
  1. inside production.py file add following:
from .base import *

ALLOWED_HOSTS = ["ip-address", "www.your-website.com"]

DEBUG = False

EMAIL_BACKEND = "django.core.mail.backends.smtp.EmailBackend"

THUMBNAIL_DEBUG = False  # incase we are using "sorl.thumbnail"
  1. In Django directory create a file named .env for environmental variables with your configuration.
# your default settings file for your environment
# Set to `project.settings.production` for production phase
SETTINGS_ENVIRONMENT=project.settings.development

SECRET_KEY=django-insecure-$p!)l2!ek!)aa)dkngex_-to#9+pmx%lhh1(h(9xe3*c$r=#5(

DB_ENGINE=django.db.backends.postgresql_psycopg2
DB_NAME=db_name
DB_USER=postgres
DB_PASSWORD=root
DB_HOST=localhost
DB_PORT=5432