Building a Django-React book-tracking app: the backend setup
A step-by-step guide at how to set up a Django backend using the Django REST framework to integrate with a React frontend
After getting warmed up with Django by making a simple to-do app using React, I wanted to level up slightly and learn how to use more than one model — to begin to understand how larger projects with more relational data tables are handled. Follow along to learn how to get a Django API with a one-to-many model relationship up and running.
What You’ll Need
You will need to have Python 3 and Node.js installed — follow the links below to download both according to your local environment:
Python installation
Node.js installation
Creating the Project
First, navigate to the directory you’ll want to host the entire application and enter the following command to make a new project:
mkdir django-react-booktracker
Navigate into that directory:
cd django-react-booktracker
Then, install Pipenv using either pip
or pip3
depending on your download:
pip install pipenv
Pipenv automatically builds and manages a virtual environment for your project, so each Python project you build can have its own dependencies (like Django), which you will not have to install globally.
To activate the virtual environment, always use the below command:
pipenv shell
Next, install Django in your virtual environment using pipenv:
pipenv install django
Now, you can create a new project and name it backend:
django-admin startproject backend
And, navigate into the backend folder:
cd backend
Next, create a new application within the backend project called booktracker:
python manage.py startapp booktracker
**Apps and projects are not interchangeable in definition or practice; a project can have multiple apps. For instance, a single project can have a blog and a book- tracker, but both should be created as separate apps.
Run initial migrations:
python manage.py migrate
And, finally, your server can be started at any time by entering the following into your virtual environment:
python manage.py runserver
You should see the below image if all went as expected —
You can quit the server at any point with CONTROL+C
.
Register the application
Although the necessary files and dependencies for the booktracker app have been installed, Django does not yet register it unless we add it into the INSTALLED_APPS
list in the settings.py
folder, located in the backend folder.
Creating the Models
Models provide the logical structure of the entire app, represented by a database. Each model maps to a database table. For a simple booktracking app, the two most obvious, or necessary, data tables include Book and Author.
Author Model
Navigate to your models.py
file located within the booktracker app folder.
first_name
andlast_name
are the properties, or fields, of the Author model, which are specialized as class attributes and mapped to their respective column in the database.- Each field is an instance of the relevant Field class, which is used to determine the datatype of the column and any validation requirements. The
CharField
option indicates that the column’s datatype is a string, requiring amax_length
argument.
After creating this model, create a migration file and then run the migration for the Author model:
python manage.py makemigrations author
python manage.py migrate author
Book Model
After these migrations are complete, set up the Book model in the same models.py
file like so —
A couple things to note in this class:
- Since a book has/belongs to an author and an author can have many books, we can represent this many-to-one relationship with the
ForeignKey
class to refer to the associated author instance. This class requires two arguments: the class to which the model is related and theon_delete
option, which will delete the model instance (i.e. book) if the related model instance (author) is deleted. - The
TextField
is also a string field, but for larger amounts of data - The
read
field requires theBooleanField
class type, which can take a default argument. If no default is given, the default value ofBooleanField
isNone
Again, you’ll need to make a migration file and run the migration for this second model:
python manage.py makemigrations book
python manage.py migrate book
Create the admin interface
An added feature of Django is its admin interface, which is essentially an internal management tool trusted users can use to handle the database. The admin interface gives automatic access to the core CRUD functionality to manage data.
Setting up this service is easy: open the admin.py
file ( booktracker/admin.py) and add the following code:
- Set
list_display
to the model properties to control which fields are displayed on the change list page of the admin.
To gain access to the admin site, create a superuser with the following command:
python manage.py createsuperuser
This command will prompt you to enter an email and create a username and password for the admin user. Once you have done so, start the server (python manage.py run server
) and navigate to http://localhost:8000/admin; you will be prompted to login and then should see a page similar to the following:
You can now add new author and book instances, as well as review, edit, or delete existing instances.
Set up the APIs
To allow users to retrieve and manage data via requests on the browser side, we need to set up an API to allow this interaction with the database.
Run the following command in the Django virtual environment to get started with building the Web API:
pipenv install djangorestframework django-cors-headers
Once you have installed that from the command line, add both ‘corsheaders’
and ‘rest_framework’
to the INSTALLED_APPS
list in the settings.py
file.
Then, to tell the frontend (served on port 3000) to interact with this API, add the following to the bottom of the settings.py
file:
Serializers
Serializers are necessary for converting model instances and SQL to JSON, which is the representation of data sent via HTTP requests between the frontend & backend.
Create a new file in the booktracker app directory and name it serializers.py
(so from the root of the project, that should be located as booktracker/serializers.py
).
Import the serializers base class from the Django REST framework, as well as all models, and make a serializer class for each model.
- Make sure to include the
id
property when defining the fields, as that will be necessary for eventually accessing, updating, or deleting resources on the client-side. - We want the associated author instance to appear in the JSON format for a book’s resource. To do that, set a variable of author equal to the already defined
AuthorSerializer
class, taking two arguments:many=False
(author instance is one-to-many books) andread_only=True
(we don’t need the option to change the author here). The data for the author will be an object/dictionary in JSON format, and will be nested within a particular book’s resource, like so:
Views
The purpose of the views file is to take an incoming Web request and return a Web response, which can be anything a Web page can display, such as the HTML contents, a redirect, etc.
Again in the booktracker app directory, open the views.py
file and write the following code:
The viewsets
base class provides the implementation for CRUD operations by default, and specifies the serializer_class
and queryset
. ViewSets are helpful to get an app up and running quickly, since repeated logic can be combined into a single class.
URLS
To handle incoming requests, the REST framework adds support for automatic URL routing, offering a quick and consistent way of wiring view logic to a set of URLs (that semantically make sense for the request).
Navigate to the urls.py
file in the backend project directory (backend/urls.py
), import the following modules, register each model router, and set the urlpatterns
variable:
- The
register()
method requires the two arguments: the prefix (the URL prefix to use for this set of routes), and the related viewset class. It can take a third optional argument, the basename, which is thebase to use for the URL names that are created(since the admin site is a built-in feature, theadmin
path was already included for us). - The
urlpatterns
variable acts as a step in URL dispatching, aiding to map between URL path expressions to Python functions (your views).
Now, we have full CRUD functionality set up for browser requests. The router class allows users to make queries to the api at the following endpoints:
localhost:8000/api/books
andlocalhost:8000/api/authors
return a list of all the books and authors, respectively.READ
andCREATE
actions occur at this endpoint/api/books/id
and/api/authors/id
return a single book and author item, respectively.PUT/PATCH
andDELETE
actions occur at this endpoint.
That’s it! The API setup is now complete, and you are ready to start building the frontend, giving users access to making API calls to retrieve and manage their own summer reading list!