Taking care of the Environment

Now that the basic local setup is in place, it is time to enhance it a bit. In this chapter we will start to make use of environment variables.

Create and ignore an .env file

Important data should not live in your code or be part of the version control. That’s where environment variables come in handy. Another advantage is, that we can set different values in different environments (hence the name).

To learn more about best practices for web apps, check out the twelve-factor methodology

Locally we will store the environment variables in an .env file. Later on GitLab and Heroku, those variables can be defined in the settings.

Create an .env file:

Terminal
touch .env

Let’s ignore the .env file to prevent Git from tracking the content of it.

Add the .env file to .gitignore:

Terminal
echo .env >> .gitignore

Load necessary modules

To easily load and get environment variables in Django, we use the python-dotenv module.

Add python-dotenv to the project:

Terminal
pip install python-dotenv

Import os and python`dotenv to the Django settings and load it:

djangoku/settings.py (Beginning of the file)
import os
from dotenv import load_dotenv

load_dotenv()

Create an easy DEBUG switch

The Django debug mode should be turned off in production. Locally or in a staging environment it might be useful to see the Django debug messages. That’s why we want to set the debug mode for the environment separately.

Change the value of DEBUG from True to this:

djangoku/settings.py::23
DEBUG = os.getenv('DEBUG', default=False) == "True"

This statement does look a bit odd, so let’s see what it does:

  1. os.getenv tries to get the DEBUG env variable.

  2. If DEBUG is not set as an env variable, DEBUG defaults to False.

  3. If the env variable is set to "True", DEBUG is set to True.

Mind that environment variables are read as strings. Therefore we must check for a "True" string, not a boolean.

When you run Django server now you will see that Django does not run in debug mode. (You may even see this: CommandError: You must set settings.ALLOWED_HOSTS if DEBUG is False.) Locally we want to continue to see debug messages.

Add DEBUG variable to the .env file and set it to True:

'.env'
echo "export DEBUG=True" >> .env

When you re-run the Django server you will see that Django does run in debug mode again.

Add another secret to the .env file

The secret key must be a large random value and it must be kept secret.

— Django Documentation, Deployment Checklist
See this (stack overflow answer) to learn more about the purpose of the secret key.

When you have a look in the settings file around line 23 you see the current value of Django’s SECRET_KEY.

djangoku/settings.py::23
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'mp#qzy1(u!!)ch!s7-d@4rybwz2-r5^l%cy699=v=uyqo%ucsv'

Since we already added this file to Git, we need to create a new SECRET_KEY, add it to our .env file as a variable and reference it in the settings file.

Start the Django shell in the terminal:

Terminal
python manage.py shell
Terminal
from django.core.management.utils import get_random_secret_key

get_random_secret_key()

Copy the output (e.g. 'NEWLY%G3GENERATEDsecret_KEY!') and add it to the .env file:

'.env'
export SECRET_KEY='NEWLY%G3GENERATEDsecret_KEY!'

Replace the SECRET_KEY string with a reference to the environment variable:

djangoku/settings.py (Beginning of the file)
SECRET_KEY = os.getenv('SECRET_KEY')

Run python manage.py runserver to see if the server starts as expected.

Commit updates

When you run git status you will see, that we changed .gitignore and djangoku/settings.py.

You should not see the .env file listed when you run git status. If you do, check if it was added correctly to .gitignore.

Before we commit our changes, we have to update requirements.txt:

Terminal
pip freeze > requirements.txt

When you run git status you should see that requirements.txt is part of the modified files list.

Now we can stage and commit all changes:

Terminal
git add .
git commit -m "Work with env variables 🔐"

Checklist

Objective: The project works with an _.env file to load environment variables.

✔︎ .env exists

Terminal
cat .env

→ Outputs the contents of the .env file including DEBUG and SECRET_KEY

✔︎ .env is not tracked in Git

Terminal
git ls-files --error-unmatch .env

→ Outputs error: pathspec '.env' did not match any file(s) known to git

✔︎ .env is ignored by Git

Terminal
git check-ignore .env

→ Outputs .env

✔︎ Django can access the env variables

Terminal
python manage.py shell
Terminal
import os
from dotenv import load_dotenv
from django.conf import settings

load_dotenv()

settings.SECRET_KEY == os.getenv('SECRET_KEY')

→ Outputs True

results matching ""

    No results matching ""