How to properly configure a new Django project.

4 minute read

Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. In this tutorial, I will show how to properly configure a new Django project and best practices to be followed while development. This tutorial also expects that you are a new Django programmer who is looking for initial best practices to be followed while setting up a Django project.

At the time of writing this post Python3.6 and following packages were used in an Ubuntu Linux system.

Package Version
Django 2.2.14
psycopg2 2.8.5
python-decouple 3.3
virtualenv 20.0.28

We will be creating a virtual environment for our Django project. It is a good practice to create a separate virtual environment for each Django project. You may want to have a different version of Django for different projects in your system. A virtual environment isolates one Django project dependencies from others. Let’s find out how.

We will be using Virtualenv a tool to create isolated Python environments.

#install virtualenv 
pip3 install virtualenv==20.0.28

Now let’s create an environment where all our python packages will be install.

#create the environment. 
virtualenv venv -p python3

The above command creates a virtual environment name ‘venv’. You can give any name to your environment. The -p takes the python version you want to use for that environment.

Activate the environment and install Django.

source venv/bin/activate
pip3 install Django==2.2.14

Once all the packages are installed we can now create a new Django project

django-admin startproject NewDjangoProject
cd NewDjangoProject

Lets test the set up by running the project.

python manage.py runserver
#Check the browser at localhost:8000

By defaut Django uses sqlite as a backend database. But we will be modifying the default configuration by changing some values in settings.py and use PostgreSQL as our backend database server. For installing PostgreSQL you can follow this link.

We will be installing two packages, one for creating a Postgres connection and another one for creating environmental variables for our project.

pip3 install psycopg2==2.8.5
pip3 install python-decouple==3.3

Now we will be modifying the settings.py file of our project so that it uses PostgreSQL as our database server. Find the DATABASES variable in our settings.py file and replace the value with the following lines of code.

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mydatabase',
        'USER': 'postgres',
        'PASSWORD': 'root',
        'HOST': 'localhost',
        'PORT': '5432',
    }
}

You can see that the Database username, password, and other values are hardcoded in the settings file. It is not a good practice to hardcode any user or system-related credentials in your code. These values are usually read from system environment variables.

We will now modify the DATABASES variable in settings file and instead of hardcoding our database credentials in code, we will ask Django to read it from environment variables. We will be using the python-decouple module to create and read environmental variables for us.

#should include this line on top of the settings file.
from decouple import config, Csv

.......
.......
.......


DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': config('DB_NAME'),
        'USER': config('DB_USER'),
        'PASSWORD': config('DB_PASSWORD'),
        'HOST': config('DB_HOST'),
        'PORT': config('DB_PORT'),
    }
}
.....
.....
.....

And create a .env file in the root folder of the project (where your manage.py file resides.) and add the following values.

SECRET_KEY=%#f5mbq*xp
DEBUG=True
DB_NAME=mydatabase
DB_USER=postgres
DB_PASSWORD=root
DB_HOST=localhost
DB_PORT=5432
ALLOWED_HOSTS= localhost, 127.0.0.1

As you can see I have also added the SECRET_KEY, DEBUG, ALLOWED_HOSTS variables to .env file. Our final settings file will look something like this below.

"""
Django settings for NewDjangProject project.

Generated by 'django-admin startproject' using Django 2.2.14.

For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""

import os
from decouple import config, Csv
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = config('SECRET_KEY')

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = config('DEBUG', cast=bool)

ALLOWED_HOSTS = config('ALLOWED_HOSTS', cast=Csv())

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'NewDjangProject.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'NewDjangProject.wsgi.application'


# Database
# https://docs.djangoproject.com/en/2.2/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': config('DB_NAME'),
        'USER': config('DB_USER'),
        'PASSWORD': config('DB_PASSWORD'),
        'HOST': config('DB_HOST'),
        'PORT': config('DB_PORT'),
    }
}

# Password validation
# https://docs.djangoproject.com/en/2.2/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/2.2/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/

STATIC_URL = '/static/'

Test the set up by running the project

python manage.py migrate
python manage.py runserver

After we have set up and ran our project successfully. We have to add our project dependencies to requirements.txt file. Create a requirements.txt file and add all the packages to it. This file is usually created in the root path of the project.

Django==2.2.14
psycopg2==2.8.5
python-decouple==3.3

Our code is now ready to ship. Initialize your code repository with Git and add your .env file to .gitignore file. This will ignore your .env file while pushing your code to GitHub or GitLab. You can also create a .env.example file with dummy values for reference.

There are many other advance practices followed by Django developers like creating multiple requirements files, multiple settings files, and multiple environment files for development and production environment separately. But all these set up has more advanced configuration and we can have another tutorial for that. I hope this helped you create and configure Django using environment variables. You can find the code at Github.