Django, a popular web framework in the Python ecosystem, is built to be flexible and secure. One way to enhance security is to avoid hardcoding sensitive information (like secret keys or database passwords) directly in the source code. Instead, such information should be stored in environment variables, which can be read into the Django application at runtime. Environment variables offer a level of abstraction and separation between configuration and code, which is beneficial in terms of security and portability.
This article provides a comprehensive guide on how to read system environment variables in a Django project.
1. Setting Up Environment Variables
Before we can read an environment variable, it must be set. On UNIX-like systems (including Linux and macOS), you can set an environment variable using the export command:
export MY_VARIABLE="My Value"
On Windows, use the set command:
set MY_VARIABLE="My Value"
2. Accessing Environment Variables in Python
In a basic Python script, you can access environment variables using the `os` module:
import os
value = os.environ.get('MY_VARIABLE')
If the environment variable isn’t set, this method returns `None`.
3. Integrating with Django
Within a Django project, there are multiple places you might want to use environment variables, such as in `settings.py`. Using the method from the previous section, you can fetch environment variables directly in the Django settings file:
import os
SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY')
However, the direct method lacks a mechanism to provide default values or type conversion. Therefore, it’s often recommended to use a package like python-decouple or django-environ to enhance this process.
Using python-decouple:
Install the package:
pip install python-decouple
Use it in your Django settings:
from decouple import config
SECRET_KEY = config('DJANGO_SECRET_KEY')
DEBUG = config('DEBUG', default=False, cast=bool)
The config function retrieves the value, and you can specify default values and even cast the data to the desired type.
Using django-environ:
Install the package:
pip install django-environ
Use it in your Django settings:
import environ
env = environ.Env()
environ.Env.read_env()
SECRET_KEY = env('DJANGO_SECRET_KEY')
DEBUG = env.bool('DEBUG', default=False)
4. Handling Mandatory and Optional Environment Variables
While some environment variables might be optional (with sensible defaults), others could be mandatory. For mandatory variables, you might want the application to raise an error if they aren’t provided.
With direct `os` usage:
SECRET_KEY = os.environ['DJANGO_SECRET_KEY'] # Raises a KeyError if not set
With `python-decouple`, a UndefinedValueError will be raised for missing mandatory variables by default:
SECRET_KEY = config('DJANGO_SECRET_KEY')
5. Storing and Managing Environment Variables
For local development, you can store environment variables in a `.env` file at the root of your project. Then, tools like `django-environ` or `python-decouple` can read from this file. However, never commit the `.env` file to version control (like git). Always add `.env` to your `.gitignore` file.
In production or other environments, set the environment variables directly on the machine or use a service like AWS Secrets Manager, HashiCorp Vault, or other secret management tools provided by cloud providers.
Conclusion
Utilizing environment variables in Django provides a layer of abstraction, improving security and project portability. Whether you’re accessing them directly through the `os` module or using utility packages like python-decouple or django-environ, this approach enables you to manage sensitive information efficiently and safely in your Django applications.