This website is made possible by displaying online advertisements to our visitors.
Please consider supporting us by disabling your ad blocker. Thank you for your support.
This website is made possible by displaying online advertisements to our visitors.
Please consider supporting us by disabling your ad blocker.

How to Use Python Decouple with Django

May 18 2021 Yacine Rouizi
Python Decouple Settings
How to Use Python Decouple with Django

Did you ever ask yourself how to separate your sensitive information, like the secret key, from your project? Well Python Decouple is the right tool for that!

Python Decouple is a package that was originally designed for Django that helps you manage the settings of an application without having to redeploy it.

If you are a developer you must have this tool in your toolbox.

Project Setup

To start with a new project open the terminal and run these commands:

$ mkdir myapp && cd $_
$ python3 -m venv venv
$ source venv/bin/activate
(venv) $ pip install django
(venv) $ django-admin startproject mysite .

How to Use Python Decouple with Django

First, let's using pip to install Python Decouple:

$ pip install python-decouple

Now we need to use the config function from the decouple module in our settings.py file:

# mysite/settings.py
from pathlib import Path
from decouple import config 

SECRET_KEY = config('SECRET_KEY')
DEBUG = config('DEBUG')
# ...
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': config('NAME'),
        'USER': config('USER'),
        'PASSWORD': config('PASSWORD'),
        'HOST': config('HOST'),
        'PORT': '',
    }
}

EMAIL_HOST = config('EMAIL_HOST')
EMAIL_PORT = config('EMAIL_PORT')
EMAIL_HOST_PASSWORD = config('EMAIL_HOST_PASSWORD')
EMAIL_HOST_USER = config('EMAIL_HOST_USER')
EMAIL_USE_TLS = config('EMAIL_USE_TLS')

# ...

This way Python Decouple will try to find these parameters in the .ini or .env file and if a parameter is not present in the file and does not have a default value (we will see later how to do it) it will raise an UndefinedValueError.

Now, we need to put all these variables in the .env, go ahead and create it at the root directory of the project (at the same level as manage.py):

SECRET_KEY=django-insecure-!wo*h78gl1t3x=exnf2e1djx0f7lg!a2ax1p(hv=dd%8(g3db
DEBUG=True

NAME=your-db-name
USER=your-db-username
PASSWORD=your-db-password
HOST=your-db-host

EMAIL_HOST=your-email-host
EMAIL_PORT=your-email-port
EMAIL_HOST_PASSWORD=your-email-host-password
EMAIL_HOST_USER=your-email-host-user

Note that Python Decouple will return strings values. However, some parameters need to be Boolean (like DEBUG), so how can we do that?

That is what the cast argument is used for.

The Cast Argument

You can add the cast argument to the config function to specify which value do you want to return.

Let's have a look at how it works:

print(type(config('DEBUG')))
<class 'str'>
print(type(config('DEBUG', cast=bool)))
<class 'bool'>

So the above configuration will become:

# mysite/settings.py
SECRET_KEY = config('SECRET_KEY')
DEBUG = config('DEBUG', cast=bool)
# ...
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': config('NAME'),
        'USER': config('USER'),
        'PASSWORD': config('PASSWORD'),
        'HOST': config('HOST'),
        'PORT': '',
    }
}

EMAIL_HOST = config('EMAIL_HOST')
EMAIL_PORT = config('EMAIL_PORT', cast=int)
EMAIL_HOST_PASSWORD = config('EMAIL_HOST_PASSWORD')
EMAIL_HOST_USER = config('EMAIL_HOST_USER')
EMAIL_USE_TLS = config('EMAIL_USE_TLS', cast=bool)

Please refer to the documentation to see what type of value the cast argument can receive.

The Default Argument

Imagine this case: In the development phase you want your DEBUG variable to be set to True while in production you want it to be set to False, can we do that without having to separate our configuration? The answer is YES!

The config function takes default as an extra argument to give default values in case there is an undefined value in the .env file.

Like I said above Python Decouple will try to find a value in the environment variables, if he can't find it, it will search it in either .ini or .env, if the value is not defined, it will search in the default argument.

Here is how you can do it:

SECRET_KEY = config('SECRET_KEY')
DEBUG = config('DEBUG', default=True, cast=bool)
# ...
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
        'NAME': config('NAME', default='rouizi-db'),
        'USER': config('USER', default='rouizi'),
        'PASSWORD': config('PASSWORD', default='1234'),
        'HOST': config('HOST'),
        'PORT': '',
    }
}
EMAIL_HOST = config('EMAIL_HOST', default='localhost')
EMAIL_PORT = config('EMAIL_PORT', default=25, cast=int)
EMAIL_HOST_PASSWORD = config('EMAIL_HOST_PASSWORD', default='')
EMAIL_HOST_USER = config('EMAIL_HOST_USER', default='')
EMAIL_USE_TLS = config('EMAIL_USE_TLS', default=False, cast=bool)

So in the development phase, if you don't put, for example, DEBUG in the .env file, Python Decouple will grab the value from the default argument.

But don't forget to specify this value in production, otherwise, Python Decouple will use the default one.

One last thing: you have to add the .env file to your .gitignore file so you don't push this sensitive information to your repository.

Summary

In this tutorial, we saw how to use Python Decouple to organize your settings and how to store them in a .env file. We also saw how to convert the values to the correct data type and how to give them a default value. Also, we learned that with Python Decouple you don't need different configuration files for development and production.

If you liked this tutorial don't forget to leave a comment below. See you in the next one.

Comments 3
Avatar Damjan Dimitrioski said
What if I use Vault by HashiCorp, that only authorizes certain apps to access certain keys, that way I don't need to have special libraries to decouple my settings.py.

May 19, 2021, 9:56 a.m.

Avatar rouizi said
@Damjan Dimitrioski I didn't use Vault by HashiCorp before but I think it's possible to use it instead of Decouple. But from what I read on their documentation, you have to install their library in order to make an API call to retrieve your API keys, secret key, or other stuff.
I think their solution is more secure because you don't have to store plain text in files, like with Decouple.

May 21, 2021, 3:25 p.m.

Avatar Yacine said
@Avi I don't think that python decouple cache the env variables, maybe you just forget to save your file after changing your env variables?

May 30, 2022, 7:15 p.m.

Leave a comment

(Your email address will not be published)