touch .env
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:
Let’s ignore the .env file to prevent Git from tracking the content of it.
Add the .env file to .gitignore:
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:
pip install python-dotenv
Import os
and python`dotenv
to the Django settings and load it:
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:
DEBUG = os.getenv('DEBUG', default=False) == "True"
This statement does look a bit odd, so let’s see what it does:
-
os.getenv
tries to get theDEBUG
env variable. -
If
DEBUG
is not set as an env variable,DEBUG
defaults toFalse
. -
If the env variable is set to
"True"
,DEBUG
is set toTrue
.
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
:
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.
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
.
# 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:
python manage.py shell
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:
export SECRET_KEY='NEWLY%G3GENERATEDsecret_KEY!'
Replace the SECRET_KEY
string with a reference to the environment variable:
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:
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:
git add .
git commit -m "Work with env variables 🔐"
Checklist
Objective: The project works with an _.env file to load environment variables.
✔︎ .env exists
cat .env
→ Outputs the contents of the .env file including DEBUG
and SECRET_KEY
✔︎ .env is not tracked in Git
git ls-files --error-unmatch .env
→ Outputs error: pathspec '.env' did not match any file(s) known to git
✔︎ .env is ignored by Git
git check-ignore .env
→ Outputs .env
✔︎ Django can access the env variables
python manage.py shell
import os
from dotenv import load_dotenv
from django.conf import settings
load_dotenv()
settings.SECRET_KEY == os.getenv('SECRET_KEY')
→ Outputs True