© The Author(s), under exclusive license to APress Media, LLC, part of Springer Nature 2021
V. GagliardiDecoupled Django https://doi.org/10.1007/978-1-4842-7144-5_5

5. Setting Up a Django Project

Valentino Gagliardi1  
(1)
Colle di Val D’Elsa, Italy
 
This chapter covers:
  • Setting up the Django project

In the following sections, we begin to lay down the structure of our Django project.

This project will accompany us for the rest of the book. It will be expanded with a REST API in Chapter 6, and later with a GraphQL API.

Setting Up the Project

To start off, create a new folder for the project and move into it:
mkdir decoupled-dj && cd $_
Note

It is a good idea to keep the project under source control with Git. You are encouraged to initialize a repo with git init as soon as you create the project folder.

Once inside the folder, create a new Python virtual environment:
python3.9 -m venv venv
For the virtual environment you can use any Python version above 3; the higher the version, the better. When the environment is ready, activate it:
source venv/bin/activate
To confirm that the virtual environment is active, look for (venv) in your command prompt. If everything is in place, install Django:
pip install django
Note

It is best to install a version of Django greater than 3.1, which has support for asynchronous views.

Next up, create your Django project:
django-admin startproject decoupled_dj .
A note on the project folder structure:
  • decoupled-dj is the repo root

  • decoupled_dj is the actual Django project

  • Django apps live in decoupled-dj

When you are ready, create two Django apps. The first app is named billing:
python manage.py startapp billing
The second app instead is a blog:
python manage.py startapp blog
A brief explanation of these apps. billing will be a Django application exposing a REST API for creating client invoices. blog will expose a REST API first, and then a GraphQL API. Now check that you have everything in place inside the project root. Run ls -1, and you should see the following output:
blog
billing
decoupled_dj
manage.py
venv

In the next section, we continue the project customization with the introduction of a custom Django user.

A Custom User

Although not strictly required for our project, a custom Django user can save you in the long run if you decide to put your project in production. Let’s create one. First off, create a new app:
python manage.py startapp user
Open users/models.py and create the custom user, as shown in Listing 5-1.
from django.contrib.auth.models import AbstractUser
from django.db.models import CharField
class User(AbstractUser):
   name = CharField(blank=True, max_length=100)
   def __str__(self):
       return self.email
Listing 5-1

A Custom Django User

We keep the custom user lean and simple with just one additional field to allow further customizations in the future. The next step would be adding AUTH_USER_MODEL to our settings file, but before doing so we need to split our settings by environment.

Tip

In the book entitled Practical Django 2 and Channels 2 by Federico Marani (the section entitled “The User Model” in Chapter 4), you’ll find another extensive example of a custom user in Django.

Interlude: Choosing the Right Database

This step has inherently nothing to do with our decoupled Django project, but using the right database is one of the most important things you can do, in any web framework. Throughout the book I will use Postgres as the database of choice. If you want to do the same, here’s how to get Postgres on your machine:
  • Postgres.app for MacOS

  • Postgres under Docker

  • Install Postgres directly on your system through a package manager

If instead you want to use SQLite, look for instructions in the next section.

Splitting the Settings File

Particularly useful when deploying in production, split settings are a way to partition Django settings depending on the environment. In a typical project, you may have:
  • The base environment, common for all scenarios

  • The development environment, with settings for development

  • The test environment, with settings that apply only to testing

  • The staging environment

  • The production environment

The theory is that depending on the environment, Django loads its settings from a .env file. This approach is known as the Twelve-Factor app, first popularized by Heroku in 2011. There are many libraries for Twelve-Factor in Django. Some developers prefer to use os.environ to avoid additional dependencies altogether. My favorite library is django-environ. For our project we set up three environments: base, development, and later production. Let’s install django-environ and psycopg2:
pip install django-environ pyscopg2-binary
(psycopg2 is required only if you use Postgres.) Next up, we create a new Python package named settings in decoupled_dj. Once the folder is in place, create another file for the base environment in decoupled_dj/settings/base.py. In this file, we import django-environ, and we place everything Django needs to run, regardless of the specific environment. Among these settings are:
  • SECRET_KEY

  • DEBUG

  • INSTALLED_APPS

  • MIDDLEWARE

  • AUTH_USER_MODEL

Remember that in the previous section we configured a custom Django user. In the base settings we need to include the custom user app in INSTALLED_APPS, and most important, configure AUTH_USER_MODEL. Our base settings file should look like Listing 5-2.
import environ
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
env = environ.Env()
environ.Env.read_env()
SECRET_KEY = env("SECRET_KEY")
DEBUG = env.bool("DEBUG", False)
INSTALLED_APPS = [
   "django.contrib.admin",
   "django.contrib.auth",
   "django.contrib.contenttypes",
   "django.contrib.sessions",
   "django.contrib.messages",
   "django.contrib.staticfiles",
   "users.apps.UsersConfig",
]
MIDDLEWARE = [ # OMITTED FOR BREVITY ]
ROOT_URLCONF = "decoupled_dj.urls"
TEMPLATES = [ # OMITTED FOR BREVITY ]
WSGI_APPLICATION = "decoupled_dj.wsgi.application
DATABASES = {"default": env.db()
AUTH_PASSWORD_VALIDATORS = [  # OMITTED FOR BREVITY  ]
LANGUAGE_CODE = "en-GB"
TIME_ZONE = "UTC"
USE_I18N = True
USE_L10N = True
USE_TZ = Tru
STATIC_URL = env("STATIC_URL")
AUTH_USER_MODEL = "users.User"
Listing 5-2

Base Settings for Our Project

Note

I have omitted for brevity the complete code for the following configurations: MIDDLEWARE, TEMPLATES, and AUTH_PASSWORD_VALIDATORS. These should have the default values that come from stock Django.

Next up we create an .env file in the decoupled_dj/settings folder. This file will have different values depending on the environment. For development we use the values in Listing 5-3.
DEBUG=yes
SECRET_KEY=!changethis!
DATABASE_URL=psql://decoupleddjango:[email protected]/decoupleddjango
STATIC_URL=/static/
Listing 5-3

Environment File for Development

If you want to use SQLite in place of Postgres, change DATABASE_URL to:
DATABASE_URL=sqlite:/decoupleddjango.sqlite3
To complete the setup, create a new file called decoupled_dj/settings/development.py and import everything from the base settings. In addition, we also customize the configuration. Here we are going to enable django-extensions, a handy library for Django in development (Listing 5-4).
from .base import *  # noqa
INSTALLED_APPS = INSTALLED_APPS + ["django_extensions"]
Listing 5-4

decoupled_dj/settings/development.py – The Settings File for Development

Let’s also install the library:
pip install django-extensions
Let’s not forget to export the DJANGO_SETTINGS_MODULE environment variable:
export DJANGO_SETTINGS_MODULE=decoupled_dj.settings.development
Now you can make the migrations:
python manage.py makemigrations
Finally, you can apply them to the database:
python manage.py migrate

In a moment, we will test our setup.

Bonus: Running Django Under ASGI

To run Django asynchronously, we need an ASGI server. In production, you can use Uvicorn with Gunicorn. In development, you might want to use Uvicorn standalone. Install it:
pip install uvicorn
Again, don’t forget to export the DJANGO_SETTINGS_MODULE environment variable if you haven’t already done so:
export DJANGO_SETTINGS_MODULE=decoupled_dj.settings.development
Next up, run the server with the following command:
uvicorn decoupled_dj.asgi:application
If everything goes well, you should see the following output:
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

If you click on the link, you should see the familiar Django rocket! One more thing before moving forward: we need to split the requirements file.

Splitting the Requirements File

As we have done with the settings file, it is good practice to split the requirements for our Django applications. We will work in development for most of the next chapters, and for now we can split the requirements in two files: base and development. Later, we will also add dependencies for testing and production. Create a new folder called requirements, and place the base.txt and development.txt files into it. In the base file, we place the most essential dependencies for our project:
  • Django

  • django-environ for working with .env files

  • pyscopg2-binary for connecting to Postgres (not required if you decided to use SQLite)

  • Uvicorn for running Django under ASGI

Your requirements/base.txt file should look like the following:
Django==3.1.3
django-environ==0.4.5
psycopg2-binary==2.8.6
uvicorn==0.12.2
Your requirements/development.txt file instead should look like the following:
-r ./base.txt
django-extensions==3.0.9
Note

Your versions of these packages will most likely be different from mine by the time you read this book.

From now on, to install the dependencies of your project, you will run the following command, where the requirements file will vary depending on the environment you are in:
pip install -r requirements/development.txt
Note

It is a good moment to commit the changes you made so far and to push the work to your Git repo. You can find the source code for this chapter at https://github.com/valentinogagliardi/decoupled-dj/tree/chapter_05_setting_up_project.

Summary

This chapter prepared the Django project and explained how to run a Django with an asynchronous ASGI server. You learned:
  • How to split settings and requirements

  • How to run Django under Uvicorn

In the next chapter, we finally get hands on with Django and JavaScript frontends.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset