Environment
settings with Django
Florian Demmer
django-environ
Django Meetup, 2017-11-07
The Twelve-Factor App
III. Config
Store config in the environment
https://12factor.net/config
A little history
-
django-admin startproject myproject
- myproject/settings.py
-
from django.conf import settings
-
settings are at "myproject.settings"
- create myproject/local_settings.py
-
import at end of myproject/settings.py
→ .gitignore!
→ multiple "locals" ... environments, stages?
Config per stage
-
make settings a package, add "stages":
- myproject/settings/__init__.py
from . base import * - myproject/settings/base.py
→ previously settings.py -
myproject/settings/dev.py
from . base import *
→ plus "local" settings
- myproject/settings/__init__.py
- settings are at "myproject.settings"
- settings are at "myproject.settings.dev"
Tell Django about stages
- "myproject.settings" and "myproject.settings.dev"
- using the environment!
-
in manage.py and wsgi.py:
os.environ.setdefault( 'DJANGO_SETTINGS_MODULE', 'myproject.settings' )
-
run: DJANGO_SETTINGS_MODULE=myproject.settings.dev ./manage.py runserver
More fine grained settings
- eg. SECRET_KEY or passwords
-
export SECRET_KEY=foobar $ python3 -c "import os; print(os.environ['SECRET_KEY'])" foobar
- works well with just strings
Introducing django-environ
-
$ export CACHE_URL=redis://localhost:6379/0 $ python -c " import environ; env=environ.Env(); print(env.cache()) " { 'LOCATION': 'redis://localhost:6379/0', 'BACKEND': 'django_redis.cache.RedisCache' }
Custom env var and defaults
-
$ python -c " import environ; env=environ.Env(); print( env.cache( 'MEMCACHED_URL', default='locmemcache://unique-snowflake') )" { 'LOCATION': 'unique-snowflake', 'BACKEND': 'django...locmem.LocMemCache' }
More parameters
-
$ export DATABASE_URL=postgresql://app:password@localhost:5432/app?ATOMIC_REQUESTS=1 $ python -c "import environ; env=environ.Env(); print(env.db())" {'ENGINE': 'django...postgresql_psycopg2', 'HOST': 'localhost', 'ATOMIC_REQUESTS': True, 'USER': 'app', 'OPTIONS': {}, 'PASSWORD': 'password', 'PORT': 5432, 'NAME': 'app'}
Required settings
-
$ python -c "import environ; env=environ.Env(); print(env.db(NO_DATABASE_URL))" Traceback (most recent call last): File "<string>", line 1, in <module> File ".../django-environ/environ/environ.py", line 207, in db_url return self.db_url_config(self.get_value(var, default=default), engine=engine) File ".../django-environ/environ/environ.py", line 280, in get_value raise ImproperlyConfigured(error_msg) django.core.exceptions.ImproperlyConfigured: Set the DATABASE_URL environment variable
Datatypes
-
$ export BOOL_=1 $ python -c "import environ; env=environ.Env(); print(env.bool('BOOL_'))" True
-
$ export FLOAT_=3,14 $ python -c "import environ; env=environ.Env(); print(env.float('FLOAT_'))" 3.14
Datatypes
-
$ export LIST_=a,b,c,d,1,2,3 $ python -c "import environ; env=environ.Env(); print(env.list('LIST_'))" ['a', 'b', 'c', 'd', '1', '2', '3']
-
$ export DICT_=foo=bar,spam=42,ham=3.14 $ python -c "import environ; env=environ.Env(); print(env.dict('DICT_'))" {'foo': 'bar', 'ham': '3.14', 'spam': '42'}
Managing environments
- .bashrc or .profile
- direnv (https://direnv.net)
- let django-environ read a file
-
$ python -c " import environ; env=environ.Env(); environ.Env.read_env('.env') "
-
- with docker-compose
- ...
All the things
-
https://12factor.net/config
-
https://django-environ.readthedocs.io/en/latest/
-
https://github.com/fdemmer/django-environ
-
my twitter: @fdemmer
-
slides: https://slides.com/fdemmer
Django Meetup, 2017-11-07
By Florian Demmer
Django Meetup, 2017-11-07
- 1,353