Image Credit: Django REST Framework

Let’s build an API with Django REST Framework

Emmanuel King Kasulani
Backticks & Tildes

--

In this first part, I will be introducing you to how you can develop an API quickly using the Django REST Framework (DRF) and Django. This first part is meant to wet your appetite and let you get a feel of developing a REST API using DRF, right out of the box with minimal code. The subsequent parts that will follow this first part in the series will be diving into more advanced concepts and features of DRF.

Traditionally, Django is known to many developers as a MVC Web Framework, but it can also be used to build a backend, which in this case is an API. We shall see how you can build a backend with it in the next section of this post.

Let’s get started

In this tutorial, you will be building a simple API for a simple music service.

Setup your development environment

For this tutorial, I am using python 3.6.3. You can check the version of Python installed on your local machine by typing this command in your shell;

$ python

You will get an output that shows you the version number of the installed Python similar to this;

Python 3.6.3 (default, Oct  4 2017, 06:09:15)[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.37)] on darwinType "help", "copyright", "credits" or "license" for more information.>>>

For Linux and Mac OS users, you can type this command in your CLI to show the python version installed;

$ python -VPython 3.6.3

Since we are going to be using django 2.0 in this tutorial, I advice that you install the latest release of Python 3.4, 3.5, or 3.6 if you don’t have it on your development machine.

After installing python, you can go ahead and create a working directory for your API and then setup a virtual environment.

For Linux and Mac OS users, you can type these commands in your CLI to setup your working directory and virtual environment;

$ mkdir music_service && cd music_service# creates virtual enviroment named venv
music_service$ virtualenv --python=python3 venv
# activate the virtual enviroment named venv
music_service$ source venv/bin/activate

Before you can use DRF to build an API you will need to first install django in the virtual environment you created earlier.

(venv)music_service$ pip install Django==2.0.3

After installing django, go ahead and install djangorestframework in the virtual environment you created earlier.

(venv)music_service$ pip install djangorestframework

Project setup

After setting up your development environment, go ahead and create a django project;

(venv)music_service$ django-admin.py startproject api .
(venv)music_service$ cd api

Then create a django app;

(venv)music_service$ django-admin.py startapp music

At this point, the directory structure should now look like this;

api/
manage.py
api/
__init__.py
settings.py
urls.py
wsgi.py
music/
migrations/
__init__.py
__init__.py
admin.py
apps.py
models.py
tests.py
views.py
venv/

With the project and app created, you now need to sync your database for the first time and create an initial user and set a password for that user.

(venv)music_service$ python manage.py migrate
(venv)music_service$ python manage.py createsuperuser --email admin@example.com --username admin

Now, open the api/settings.py file and add the rest_framework and music apps to INSTALLED_APPS .

INSTALLED_APPS = [
...
'rest_framework',
'music'
]

Furthermore, open the api/urls.py file and add urls for the music app;

...from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('music.urls'))
]

For this tutorial, I am using the default sqlite that comes with django as my Relational DataBase Management System. You can use postgres or any other RDBMS you prefer.

With that you now have your project setup and ready to code the music service api.

Tests Driven Development

Code without tests is broken as designed.

Jacob Kaplan-Moss

Before you can code the business logic of your API, you will need to write a test. The kind of approach I prefer is: Write a unit test for a single view and then update the code to make that test pass.

Write a test for the GET songs/ endpoint

To illustrate this approach, let’s create a test for the end point that returns all songs: GET songs/.

Open the music/tests.py file and add the following lines of code;

When you attempt to run tests at this point, it will fail, with errors since we have not yet created the view file and the serializer.

Create the View for GET songs/ endpoint

After writing the test, you can go ahead and code the view that will respond to the request GET songs/ .

Model: First, create a model that will store the data about the songs that will be returned in the response. Open the music/models.py file and the following lines of code;

Since we are using django , we can also add our model to the admin. We shall see a little bit later how we can use the admin section to add songs, so that we can manually test this endpoint. Go ahead add the following lines of code to the music/admin.py file.

There after make-migrations;

(venv)music_service$ python manage.py makemigrations

Then migrate;

(venv)music_service$ python manage.py migrate

Serializer: Second, create a serializer. Serializers allow complex data such as querysets and model instances to be converted to native Python datatypes that can then be easily rendered into JSON, XML or other content types.

Add a new file music/serializers.py and add the following lines of code;

Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data. The serializers in REST framework work very similarly to Django’s Form and ModelForm classes. A complete documentation about serializers can be found here for your reference.

View: Finally, go ahead and create a view that returns all songs. Open the music/views.py file and the following lines of code;

For someone coming from using flask to build an api using DRF, the idea of using viewsets is similar to using Resources.

In the code above we specify how to get the objects from the database by setting the queryset attribute of the class and specify a serializer that will be used in serializing and deserializing the data.

The view in this code inherits from a generic viewset ListViewSet . A complete documentation about generic viewsets can be found here for your reference.

Wiring up the views

Before you can run the tests, you will have to link the views by configuring the urls.

Open the api/urls.py file and add the following lines of code;

Open the music/urls.py file and add the following lines of code;

Now let’s test!

It’s that moment of truth. First, let’s run automated tests. Run the command;

(venv)music_service$ python manage.py test

The ouput in your shell should be similar to this;

Creating test database for alias 'default'...
System check identified no issues (0 silenced).
.
--------------------------------------------------------------------Ran 1 test in 0.010s
OK
Destroying test database for alias 'default'...

You can also manually test this endpoint. Navigate to http://127.0.0.1:8000/admin in your browser and login with the super user credentials that you added during the setup phase of the project. Once logged in, you will have an interface before you that looks like this;

Click on songss in the MUSIC section and you will have an interface before that looks like this;

Click on ADD SONGS button and add songs for testing purposes. When you are done, Navigate to http://127.0.0.1:8000/api/v1/songs and you will have interface that looks like this;

If you can see the songs you added, you can high five your self. Congratulations, your API works!

Bonus: API versioning

An API is a contract between the backend and clients that consume it. API versioning allows you to alter behavior between different clients and “politely” deprecate old code for old clients. You should consider adding versioning to your API.

To add versioning, open the api/settings.py file and add the following lines of code.

When API versioning is enabled, the request.version attribute will contain a string that corresponds to the version requested in the incoming client request. Like in the sample code below, we can access the version attribute and alter the behaviour of our API depending on the version number.

Take aways

So far we have seen how it’s so easy to create an API using DRF. In this tutorial, I only implement one endpoint of the API with the aim of keeping the tutorial simple just to give you a feel of how to use this framework. You can actually build a powerful API using DRF.

The table below is a complete list of all the endpoints implemented in this project. For a complete implementation of the API example, go to my git hub repo, fork it and play around with it as you learn.

Benefits of using DRF

  1. DRF have a Browsable API feature. This feature supports generating human-friendly HTML output for each endpoints in your API. These pages allow for easy browsing of resources, as well as forms for submitting data to the resources using POST, PUT, and DELETE.
  2. DRF provides an authentication feature you can use on views to authenticate requests for resources in your API.
  3. DRF provides a permissions feature you can use on views to protect resources in your API.
  4. DRF provides a throttling feature you can use on views to control the rate of requests that clients can make to an API.
  5. DRF supports filtering.
  6. DRF supports pagination.
  7. DRF supports API versioning as we have seen earlier.

Additional resources

I highly recommend this resource if you are building your API. It’s the ultimate guide on the best practices to follow while building your API.

I also recommend the official DRF and Django documentations.

I also found this resource from cdrf.co useful. It gives a detailed description of all classes in the DRF framework incase you want to view their structure.

In the second part, i will be discussing authentication and permissions in DRF and how we can apply them to the music service API endpoints.

I hope this was helpful to you and I want to thank you for reading this post. Hit clap in case it was helpful so that others may find it too. You can also suggest in the comment section how I can improve on this post to help you understand the Django REST Framework.

--

--