Welcome to django-envy’s documentation!¶
Django-envy is an opinionated environment variable parser, with a focus on strictness, and doing a single thing well. Can be used standalone or with Django.
Motivation¶
With the 12-factor app gaining popularity, and an increased focus on devops, there’s already quite a few packages out there which can read and parse environment variables. However, django-envy makes a series of design decisions that I feel are important.
In the following, I will go over each decision in turn, and lay out the reasoning for it.
.env
Files Are Not Environment Variables¶
The 12-factor app “manifesto” is very clear on favoring environment variables over language or OS specific config files for configuration, for a number of very good reasons.
While it’s possible to interpret these reasons and conclusions in different ways, django-envy takes a very opinionated stand: The application should know absolutely nothing about where environment variables come from.
There are dozens of ways to set an environment variable so that it will be available to your application:
- Globally on startup for the entire instance
- For a specific user
- In your process manager, whether that be
startup
,runit
,supervisor
,system.d
,god
,monit
, or something entirely different - Using a wrapper script
- Built into your docker image
- When starting your docker image
- From a series of files using
envdir
- Sourcing a bash script
- Etc.
All of these are acceptable options, and each have their pros and cons. With so many ways to set environment variables, there’s no reason for the application to be able to set them too.
If you need to set environment variables in development, consider something like foreman or honcho, or the built in facilities for doing so in docker, if that’s what you use.
Don’t Duplicate Packages¶
There are a number of well-maintained packages to take care of Django-specific settings, such as database, cache or email settings:
- dj-database-url
- dj-email-url
- django-cache-url
However much the naming inconsistency annoys me, I don’t see a good reason to duplicate the functionality of these packages, for the sake of fewer dependencies.
For an example of how to use any of these packages with django-envy, please see …
Strictness And Correctnes Above Convenience¶
Configuration is important, and getting a vital piece of information wrong can be devastating. That’s why django-envy takes a firm stance on what values are allowed when casting between types, and will always prefer raising an error to trying to be clever.
Examples:
- There is only two acceptable values when casting to boolean:
"true"
and"false"
(they are case insensitive though) - Floats must always be specified using a period (
.
) as the decimal separator. There is no logic for “guessing” the thousand separator. (Though it is possible to use_
for readability as in Python 3.6) - If a cast does not seem to make sense, django-envy will throw an error. This includes trying to cast to nested collections.
Alternatives¶
If these design decisions aren’t to your liking, there are other packages out there, which have chosen a different set of tradeoffs:
- django-environ
- envparse
- python-decouple
- django12factor
- django-confy
- json_environ
Usage¶
Creating an Environment¶
Reading Environment Variables¶
Providing Defaults¶
Convenience Methods¶
Using With Other Django Settings Packages¶
API¶
-
class
envy.
Environment
(environ)[source]¶ Class for reading and casting environment variables
This class presents the main interface for interacting with the environment. Once instantiated, it can either be called as a function, or any of the convenience methods can be used.
Parameters: environ (dict) – Environment to read variables from -
__call__
(var, default=<class 'envy.NoValue'>, cast=None, force=True)[source]¶ Function interface
Once the environment has been initialised, it can be called as a function. This is necessary to provide custom casting, or it can sometimes be preferred for consistency.
Examples
Casting an environment variable:
>>> env = Environment({'MY_VAR': '1'}) >>> env('MY_VAR', cast=int) 1
Providing a default:
>>> env = Environment({}) >>> env('ANOTHER_VAR', default='value') "value"
Parameters: - var (str) – The name of the environment variable
- default – The value to return if the environment variable does not exist
- cast – type or function for casting environment variable. See casting
- force (bool) – Whether to force casting of the default value
Returns: The environment variable if it exists, otherwise default
Raises:
-
__contains__
(var)[source]¶ Test if an environment variable exists
Allows using the
in
operator to test if an environment variable exists.Examples
>>> env = Environment({'MY_VAR': '1'}) >>> 'MY_VAR' in env True >>> 'ANOTHER_VAR' in env False
-
bool
(var, default=<class 'envy.NoValue'>, force=True)[source]¶ Convenience method for casting to a bool
-
decimal
(var, default=<class 'envy.NoValue'>, force=True)[source]¶ Convenience method for casting to a decimal.Decimal
Note
Casting
-
dict
(var, default=<class 'envy.NoValue'>, cast=None, force=True)[source]¶ Convenience method for casting to a dict
Note
Casting
-
float
(var, default=<class 'envy.NoValue'>, force=True)[source]¶ Convenience method for casting to a float
-
int
(var, default=<class 'envy.NoValue'>, force=True)[source]¶ Convenience method for casting to an int
-
json
(var, default=<class 'envy.NoValue'>, force=True)[source]¶ Get environment variable, parsed as a json string
-
list
(var, default=<class 'envy.NoValue'>, cast=None, force=True)[source]¶ Convenience method for casting to a list
Note
Casting
-
set
(var, default=<class 'envy.NoValue'>, cast=None, force=True)[source]¶ Convenience method for casting to a set
Note
Casting
-
str
(var, default=<class 'envy.NoValue'>, force=True)[source]¶ Convenience method for casting to a str
-