django-environ Configuration
django-environ is a Python library that allows Django applications to be configured using 12-factor inspired environment variables. It simplifies parsing various types of settings (e.g., databases, caches, emails, booleans, integers) from `os.environ` or `.env` files into Django-compatible formats. The current version is 0.13.0, with a release cadence that generally follows Django versions and addresses bug fixes.
Warnings
- breaking The `environ.Env` object no longer inherits from `dict` as of version 0.10.0. This means you cannot treat `env` as a dictionary (e.g., `env['KEY']` or `dict(env)`) directly. Access variables using the callable `env('KEY')` or its type-casting methods like `env.bool('KEY')`.
- gotcha For explicit `.env` file loading, ensure `environ.Env.read_env()` is called before `env()` attempts to access variables from the `.env` file. While `environ` attempts to implicitly read `.env` on first access, explicit calls with a correct path (e.g., `environ.Env.read_env(os.path.join(BASE_DIR, '.env'))`) provide better control and prevent unexpected behavior.
- gotcha All variables accessed directly with `env('KEY')` are returned as strings. To get booleans, integers, URLs, or other types, you must use the specific type-casting methods (e.g., `env.bool('DEBUG')`, `env.int('TIMEOUT')`, `env.db('DATABASE_URL')`, `env.cache('CACHE_URL')`, `env.url('SITE_URL')`) or define the casting in the `Env` constructor `env = environ.Env(DEBUG=(bool, False))`.
- gotcha The `SECRET_KEY` is a critical setting. While `django-environ` allows you to retrieve it via `env('SECRET_KEY')`, generating and managing it securely is paramount. Avoid hardcoding a default in production, and ensure it's loaded from a truly secure environment variable or a robust secrets manager.
Install
-
pip install django-environ
Imports
- Env
from environ import Env
- Path
from environ import Path
- InvalidPathSetting
from environ import InvalidPathSetting
Quickstart
import environ
import os
# --- Simulate environment variables for a runnable example ---
# In a real application, these would come from your actual .env file or OS environment.
# For local testing, you might create a .env file like:
# SECRET_KEY=your-super-secret-key-from-env
# DEBUG=True
# DATABASE_URL=sqlite:///myproject.sqlite3
# EMAIL_URL=smtp://user:password@smtp.example.com:587
# CACHE_URL=redis://localhost:6379/1
# ------------------------------------------------------------
os.environ.setdefault('SECRET_KEY', 'your-super-secret-key-for-dev-fallback')
os.environ.setdefault('DEBUG', 'True')
os.environ.setdefault('DATABASE_URL', 'sqlite:///myproject.sqlite3')
os.environ.setdefault('EMAIL_URL', 'smtp://user:password@smtp.example.com:587')
os.environ.setdefault('CACHE_URL', 'redis://localhost:6379/1')
# Initialize the Env object.
# You can set default types and values here if not found in .env or os.environ.
env = environ.Env(
# default type for DEBUG is bool, default value is False if not set
DEBUG=(bool, False)
)
# Optional: Explicitly read .env file. By default, Env.read_env() looks for .env
# in the current directory and its parents. If you don't call this, it implicitly
# reads it on the first call to env() or similar, but explicit is better for control.
# Note: This line assumes a .env file exists. For this example, we're relying on os.environ.setdefault.
# environ.Env.read_env()
# Accessing environment variables with type casting
SECRET_KEY = env('SECRET_KEY')
DEBUG = env('DEBUG') # Uses the (bool, False) casting defined above
# Complex settings like database or cache URLs are parsed into Django-compatible dictionaries
DATABASES = {
'default': env.db() # uses DATABASE_URL from environment
}
CACHES = {
'default': env.cache() # uses CACHE_URL from environment
}
EMAIL = env.email() # uses EMAIL_URL from environment
print(f"SECRET_KEY: {SECRET_KEY}")
print(f"DEBUG: {DEBUG} (type: {type(DEBUG)})")
print(f"DATABASES (default): {DATABASES['default']}")
print(f"CACHES (default): {CACHES['default']}")
print(f"EMAIL (default): {EMAIL}")
# Example of a missing variable with a default
APP_VERSION = env('APP_VERSION', default='1.0.0')
print(f"APP_VERSION: {APP_VERSION}")