Book Image

Django 3 Web Development Cookbook - Fourth Edition

By : Aidas Bendoraitis, Jake Kronika
Book Image

Django 3 Web Development Cookbook - Fourth Edition

By: Aidas Bendoraitis, Jake Kronika

Overview of this book

Django is a web framework for perfectionists with deadlines, designed to help you build manageable medium and large web projects in a short time span. This fourth edition of the Django Web Development Cookbook is updated with Django 3's latest features to guide you effectively through the development process. This Django book starts by helping you create a virtual environment and project structure for building Python web apps. You'll learn how to build models, views, forms, and templates for your web apps and then integrate JavaScript in your Django apps to add more features. As you advance, you'll create responsive multilingual websites, ready to be shared on social networks. The book will take you through uploading and processing images, rendering data in HTML5, PDF, and Excel, using and creating APIs, and navigating different data types in Django. You'll become well-versed in security best practices and caching techniques to enhance your website's security and speed. This edition not only helps you work with the PostgreSQL database but also the MySQL database. You'll also discover advanced recipes for using Django with Docker and Ansible in development, staging, and production environments. By the end of this book, you will have become proficient in using Django's powerful features and will be equipped to create robust websites.
Table of Contents (15 chapters)

Handling sensitive settings

When working when configuring a Django project, you will surely deal with some sensitive information, such as passwords and API keys. It is not recommended that you put that information under version control. There are two main ways to store that information: in environment variables and in separate untracked files. In this recipe, we will explore both cases.

Getting ready

Most of the settings for a project will be shared across all environments and saved in version control. These can be defined directly within the settings files; however, there will be some settings that are specific to the environment of the project instance or that are sensitive and require additional security, such as database or email settings. We will expose these using environment variables.

How to do it...

To read sensitive settings from the environment variables, perform these steps:

  1. At the beginning of settings/_base.py, define the get_secret() function as follows:
# settings/_base.py
import os
from django.core.exceptions import ImproperlyConfigured

def get_secret(setting):
"""Get the secret variable or return explicit exception."""
try:
return os.environ[setting]
except KeyError:
error_msg = f'Set the {setting} environment variable'
raise ImproperlyConfigured(error_msg)
  1. Then, whenever you need to define a sensitive value, use the get_secret() function, as shown in the following example:
SECRET_KEY = get_secret('DJANGO_SECRET_KEY')

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': get_secret('DATABASE_NAME'),
'USER': get_secret('DATABASE_USER'),
'PASSWORD': get_secret('DATABASE_PASSWORD'),
'HOST': 'db',
'PORT': '5432',
}
}

How it works...

If you run a Django management command without the environment variable set, you will see an error raised with a message, such as Set the DJANGO_SECRET_KEY environment variable.

You can set the environment variables in the PyCharm configuration, remote server configuration consoles, in the env/bin/activate script, .bash_profile, or directly in the Terminal like this:

$ export DJANGO_SECRET_KEY="change-this-to-50-characters-long-random-
string"

$ export DATABASE_NAME="myproject"
$ export DATABASE_USER="myproject"
$ export DATABASE_PASSWORD="change-this-to-database-password"

Note that you should use the get_secret() function for all passwords, API keys, and any other sensitive information that you need in your Django project configuration.

There's more...

Instead of environment variables, you can also use text files with sensitive information that won't be tracked under version control. They can be YAML, INI, CSV, or JSON files, placed somewhere on the hard disk. For example, for a JSON file, you would have the get_secret() function, like this:

# settings/_base.py
import os
import json


with open(os.path.join(os.path.dirname(__file__), 'secrets.json'), 'r')
as f:
secrets = json.loads(f.read())


def get_secret(setting):
"""Get the secret variable or return explicit exception."""
try:
return secrets[setting]
except KeyError:
error_msg = f'Set the {setting} secret variable'
raise ImproperlyConfigured(error_msg)

This reads a secrets.json file from the settings directory and expects it to have at least the following structure:

{
"DATABASE_NAME": "myproject",
"DATABASE_USER": "myproject",
"DATABASE_PASSWORD": "change-this-to-database-password",
"DJANGO_SECRET_KEY": "change-this-to-50-characters-long-random-string"
}

Make sure that the secrets.json file is ignored from the version control, but for convenience, you can create sample_secrets.json with empty values and put it under version control:

{
"DATABASE_NAME": "",
"DATABASE_USER": "",
"DATABASE_PASSWORD": "",
"DJANGO_SECRET_KEY": "change-this-to-50-characters-long-random-string"
}

See also

  • The Creating a project file structure recipe
  • The Working with Docker containers for Django, Gunicorn, Nginx, and PostgreSQL recipe