django environ
Installation
Splitting the Settings File
Particularly useful when deploying in production, split settings are a way to partition Django settings depending on the environment. In a typical project, you may have:
- The
base
environment, common for all scenarios - The
development
environment, with settings for development - The
test
environment, with settings that apply only to testing - The
staging
environment - The
production
environment
The theory is that depending on the environment, Django loads its settings from a .env
file. This approach is known as the Twelve-Factor app, first popularized by Heroku in 2011.
There are many libraries for Twelve-Factor in Django. Some developers prefer to use os.environ
to avoid additional dependencies altogether. My favorite library is django-environ
.
For our project we set up three environments: base, development, and later production.
Once the folder is in place, create another file for the base environment in decoupled_dj/settings/base.py
. In this file, we import django-environ, and we place everything Django needs to run, regardless of the specific environment. Among these settings are:
Abstract
- SECRET_KEY
- DEBUG
- INSTALLED_APPS
- MIDDLEWARE
- AUTH_USER_MODEL
Remember that in the previous section we configured a custom Django user. In the base settings we need to include the custom user app in INSTALLED_APPS, and most important, configure AUTH_USER_MODEL. Our base settings file like this:
Base Settings for Our Project
import environ
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
env = environ.Env()
environ.Env.read_env()
SECRET_KEY = env("SECRET_KEY")
DEBUG = env.bool("DEBUG", False)
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"users.apps.UsersConfig",
]
MIDDLEWARE = [ # OMITTED FOR BREVITY ]
ROOT_URLCONF = "decoupled_dj.urls"
TEMPLATES = [ # OMITTED FOR BREVITY ]
WSGI_APPLICATION = "decoupled_dj.wsgi.application
DATABASES = {"default": env.db()
AUTH_PASSWORD_VALIDATORS = [ # OMITTED FOR BREVITY ]
LANGUAGE_CODE = "en-GB"
TIME_ZONE = "UTC"
USE_I18N = True
USE_L10N = True
USE_TZ = Tru
STATIC_URL = env("STATIC_URL")
AUTH_USER_MODEL = "users.User"
Note I have omitted for brevity the complete code for the following configurations: MIDDLEWARE, TEMPLATES, and AUTH_PASSWORD_VALIDATORS. These should have the default values that come from stock Django.
Next up we create an .env file in the decoupled_dj/settings
folder. This file will have different values depending on the environment. For development we use the values in Listing.
Environment File for Development
DEBUG=yes
SECRET_KEY=!changethis!
DATABASE_URL=psql://decoupleddjango:localpassword@127.0.0.1/decoupleddjango
STATIC_URL=/static/
If you want to use SQLite in place of Postgres, change DATABASE_URL to:
To complete the setup, create a new file called decoupled_dj/settings/development.py
and import everything from the base settings. In addition, we also customize the configuration. Here we are going to enable django-extensions
, a handy library for Django in development
The Settings File for Development
# noqa
from .base import *
INSTALLED_APPS = INSTALLED_APPS + ["django_extensions"]
Let’s also install the library:
Use ALLOWED_HOSTS
in .env
# settings.py
import environ
# Initialize environment variables
env = environ.Env()
environ.Env.read_env()
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = env.bool('DEBUG', default=False)
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = env('SECRET_KEY', default='your-default-secret-key')
# Define ALLOWED_HOSTS based on DEBUG
if DEBUG:
ALLOWED_HOSTS = ['*'] # Allow all hosts during development
else:
ALLOWED_HOSTS = env.list('ALLOWED_HOSTS', default=['.example.com'])
# Other settings...