Let’s build an API with Django REST Framework
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, includeurlpatterns = [
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.
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
- 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
, andDELETE
. - DRF provides an authentication feature you can use on views to authenticate requests for resources in your API.
- DRF provides a permissions feature you can use on views to protect resources in your API.
- DRF provides a throttling feature you can use on views to control the rate of requests that clients can make to an API.
- DRF supports filtering.
- DRF supports pagination.
- 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.