In this series we will go over the basics of using the Django Rest Framework to build an API. In this first tutorial we will go over some basic set up and concepts that we will use in future additions to this series. This first tutorial will follow the quickstart in the documentation. Later we will spend some time with each of these concepts in more detail but for now we just need to get something started.

Project Setup

Before we do anything else we need to set up our project. First let’s create a directory for the project, install everything and create a django project.

mkdir music_api_tutorial
cd music_api_tutorial
# Create a virtual environment to isolate our package dependencies locally
python3 -m venv env
source env/bin/activate # On Windows use `env\Scripts\activate`
# Install Django and Django REST framework into the virtual environment
pip install django
pip install djangorestframework
# Set up a new project with a single application
django-admin startproject music_api .
cd music_api
django-admin startapp catalog
cd ..

Now that we have a project we need to make sure we add restframework to our installed_apps in our file.



In this first tutorial we are just going to follow the documentation to set up a basic serializer, view and url. We will go into more detail how each of these individual pieces work in the future but for now we will just stick to a basic example. First we need to set up a serializer. A serializer will handle converting between the Django model object to native Python data types that we can easily render into JSON to send as a response from our API. Luckily, Django has a lot of built in classes to make this easier for us. Let’s use one of those now.

from django.contrib.auth.models import User, Group
from rest_framework import serializers
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ['url', 'username', 'email', 'groups']
class GroupSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Group
fields = ['url', 'name']

We set up a user serializer and a group serializer. These both came from built-in models so we don’t have to worry about defining what a user or a group is, that comes with Django when we install it.


Now we need to actually create the endpoints that are used to interact with the API. Let’s set up the user and group viewsets just like how the documentation does. For now all we need to know is that viewsets will handle all of the create, read, update, and delete operations for us.

from django.contrib.auth.models import User, Group
from rest_framework import viewsets
from rest_framework import permissions
from tutorial.quickstart.serializers import UserSerializer, GroupSerializer
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all().order_by('-date_joined')
serializer_class = UserSerializer
permission_classes = [permissions.IsAuthenticated]
class GroupViewSet(viewsets.ModelViewSet):
queryset = Group.objects.all()
serializer_class = GroupSerializer
permission_classes = [permissions.IsAuthenticated]

This handles everything we need for our views. Now we need a way to access the view. That is where our urls come into play.


Let’s set a url pattern to access both views. To set this, we can use the path() function and set a pattern, the view, and optionally we can set a name. The pattern will be the actual url that the user goes to, the view will be the function view, class view or viewset being used at this url pattern. If it is a class view or a view set, you will need to add .as_view() after the view name. The optional name can make referencing the url in other parts of the api easier.

from django.urls import include, path
from rest_framework import routers
from tutorial.quickstart import views
router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'groups', views.GroupViewSet)
# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
path('', include(router.urls)),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))

Since we are using a viewset, we can also use the router. A router will handle the different url patterns that the viewset will need automatically. For example, the users viewset needs two urls. /users/ will have get and post methods for getting all users and creating a new user. /users/<id>/ will have get, post, put, delete for updating or getting a specific user by it’s id. <id> will be replaced by an id. In this case we are using the DefaultRouter, there are other options available but for a basic example this will work fine. We also need to include the router in its own path() for it to work which we did as well.


Finally let’s set up some basic pagination settings.

'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',

Testing the API

Now we should have everything set up. We can test it by doing the following.

python3 runserver

Now you have two options to test, either open up an api client like postman or insomnia and test the url routes that way or since we set it up in our urls, we can also go to http://localhost:8000 and test it through the browser.

We will stop here for this tutorial. We will come back and go through each of these pieces in more detail later to gain a better understanding about how all of this works.