Using Django REST Framework to Quickly Get a Working API

Fabricio Saavedra
NicaSource
Published in
6 min readAug 30, 2022

Despite starting as a successor of a “teachable” programming language project, Python has made a long way and, by 2022 is still one of the most popular and required programming languages in job openings with no sight of a trend turn.

bit.ly/dev-Python-NS9

In web development, there are trendy frameworks written in Python and used in different scenarios. One of the most robust options is Django, which allows us to build complete web applications (front-end and backend) with an ORM included for SQL-type databases (no need to install external libraries to develop).

Despite having the ability to build interfaces, it doesn’t mean you need to build the front-end using plain Django. Dynamic content may be tricky if you’re unfamiliar with templates similar to Jinja. If you know some front-end library or framework, you could pair that with an API built in Django; that’s where things get interesting! You can power up your web app with the features of React. The Django REST Framework (DRF) is a library that provides multiple tools to quickly set up a working API, including class-based views and serializers.

In this three-part series of articles, we’ll build this API for a mechanic shop by setting up the project, describing some endpoints, and laying out permission classes for them.

1) Setting up the project

I’ll assume you’re working with a UNIX-like system, so you’ll probably want to make a new folder for this project and create a Python environment with the tool you deem suitable. I’ll use venv:

mkdir mechanicshop
cd mechanicshop
python -m venv env
source env/bin/activate
pip install django djangorestframework

In the environment, you will be able to start a project (a group of apps/services) by executing:

django-admin startproject mechanicapi

The command will add a series of folders and files inside the mechanicapi directory.

Initial directory structure.

Out of the above shown structure, two modules are fundamental, settings.py and manage.py. In the first one, you will describe configurations for your project, such as database connections, middleware, and installed apps (apps that will run in this project). In the latter, we have a command-line utility to interact with the project differently. By using the manage.py utility, we will add apps to our project. Say we want our app to handle the vehicles inventory of a mechanical shop.

We will start by adding a vehicles to the app:

python manage.py startapp vehicles

We will then want a service to handle the customers’ data:

python manage.py startapp customers

By running the previous command, we will add some template files to a folder. The files will be named after each app we created in the previous steps. As a result, we will have a directory with a similar structure to the one shown below:

The mechanicapi project contains two services: customers and vehicles.

If we want Django to recognize the services, we need to include them in the settings.py module:

Above you can see how it should look in the settings.py module.

The next step will be to add the URL config to the project’s URL for each service we defined. The previous needs to be made because we will be hitting the endpoints by making requests to URLs. For example, to add the URL config for the customer service:

  • Go to the service directory and create a urls.py module.
    – We’ll then revisit this section.
  • Then go to the project level urls.py module, import the customers module, and add the service URL config.

Repeat the process above for the vehicles service, and you’ll end up with something like this:

Now, we are ready to define models for each service. Usually, models translate to a table in your database (unless you say otherwise). For the sake of this article, we’ll define only two models, one for each service.

  1. The Vehicle model, which is meant to represent cars, but motorcycles could also be considered eligible.

2. The Customer model will represent the customers’ contact information. We won’t have them signing up in any place, so it won’t be a one-to-one relation with the user model from django.contrib.

To wrap up this first part of the series, we’ll return to the URL config of the services. If the front-end app hits the endpoints from the API, the data will persist in our database . In the URL config module for the vehicles service, we’ll add paths (as a list called urlpatterns) so that a client can make requests to those paths and get or modify information related to vehicles.

The path function takes four arguments, out of which, two are required.

  • The first argument is the route.
    – In this example, you’d request https://somedomain.com/api/vehicles/
  • The second one is the view.
    – These are functions or classes responsible for handling the request.
  • The third and fourth are keyword arguments.
    – The order in which you specify them doesn’t matter as long as you prepend the correct key for them. The arguments will have default values if you don’t define the actual parameter in your function call, which makes them optional. Following the function signature from the documentation, the third argument is kwargs, meant to receive a python dictionary with additional information. The fourth is a developer-friendly name (so you can refer to this path more easily while testing, for example).

As you may have noticed, to pass the second argument, we had to (1) import the views module, (2) call its attribute VehiclesList, and then (3) call the as_view method on it.

What does that mean?…
You could go and read the docs, or … wait until part II of this series!

But before I let you go, let’s make some manual checks!

To ensure that the models we have defined comply with the rules expected by the Django ORM, we’ll generate the migration files for each service. The migration files describe the changes in the models that we want to propagate to the database schema. Making these kinds of changes is a two-step process. First, we will tell Django to generate the migration files for all the installed apps based on model changes we defined (unless you tell it differently):

python manage.py makemigrations

If everything goes okay, you’ll see a summary of the migration files created in your terminal and new modules in the migration directory for each app with model changes. If, on the contrary, something fails, you’ll get some exception displayed that will put you in the right direction to fix eventual issues. Pro tip: If you are new to Django, it probably be something related to the field definitions.

0001_initial.py denotes the creation of the database table based on the model description

Then, we’ll want to ‘commit’ the changes described in the migration files to our database schema, by migrating, which is synchronizing the database state with the current set of models and migrations.

python manage.py migrate

This last command will generate a SQLite3 database, unless you have changed the database configuration in the settings.py module.

At this point, you’d be tempted to run the app, but so far, we didn’t define VehiclesList, so if you went and tried to run the app, some error might have jumped at you. But don’t worry, that result is normal at this point. At least we have our models and database ready to start storing information.

In part II, we’ll review the juice of this series of articles: class-based views and serializers. We’ll realize how these resources allow us to combine information from different models in one object.

See you again in part II!

--

--