Django DRF

Django REST Framework -- Quickstart

For personal needs, I became interested in the development of API REST in Django. I then discovered the Django REST framework, also called DRF. Here is an introduction to this framework.

As indicated on the official website, Django REST framework is a powerful and flexible tool to create web APIs. That's exactly what we're going to do!

Django in a Docker container

By choice, we will do this tutorial in a basic docker container. To start, we need a Dockerfile that will allow us to create our image. Here is the content of this file :

FROM python:3.8

# Setup env vars
ENV PYTHONBUFFERED 1
ENV PYTHONPATH /app

# Add arg for package installation
ARG DEBIAN_FRONTEND=non-interactive

# Setup working dir
RUN mkdir /app
WORKDIR /app

# Keep packages up-to-date and clean afterwards
RUN apt-get update && apt-get upgrade -y \
    && rm -rf /var/lib/apt/lists/*

# Install python packages with pip
COPY requirements.txt /app/
RUN pip install -r requirements.txt

# Copy source code
COPY src /app/

# Expose port 8000
EXPOSE 8000

# Startup command to run
CMD [ "python", "manage.py", "runserver", "0.0.0.0.0:8000" ]

A few explanations are in order. We start from a python image in version 3.8 so we don't have to reinvent the wheel. The installation of the packages is done using the requirements.txt file, present at the root of the project. For our example, it contains the following lines :

Django==3.0.5
djangorestframework==3.11.0

The source code is in the src/ directory, which is currently empty.

It's time to build our Docker image. This is done with the following command:

docker build -t tutoapi:0.0.1 .

It is good practice to specify a tag for the image, here 0.0.1.

Project initialization

Now we need to connect to the container to create our project. In order to carry out this step, we are going to assemble the project folder in the container. Under Linux, the command to run is the following:

cd src/
docker run --rm -it -p 8000:8000 -v $PWD:/app tutoapi:0.0.1 bash
django-admin startproject tutoapi.
cd tutoapi.
django-admin startapp api
cd...
python manage.py migrate
python manage.py runserver 0.0.0.0:8000

The app launches on port 8000 (http://localhost:8000).

Django start page

Last preliminary step before getting to the heart of the matter, let's create an administrator for our site:

python manage.py createsuperuser --email admin@example.com --username admin

Discovery of DRF

We are now ready to start on Django REST Framework!

Serializers

First, we need to define serializers to model our objects. The file src/tutoapi/api/serializers.py (file to be created) contains the following code :

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']

Here we base ourselves on two Django models, User and Group.

In connection with each model, a "serializer" class is declared. It also declares the fields we are interested in.

Views

We now need to declare views to interact with our objects. This is done in the src/tutoapi/api/views.py file:

from django.contrib.auth.models import User, Group
from rest_framework import viewsets
from rest_framework import permissions
from tutoapi.api.serializers import UserSerializer, GroupSerializer


class UserViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = User.objects.all().order_by('-date_joined')
    serializer_class = UserSerializer
    permission_classes = [permissions.IsAuthenticated]


class GroupViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows groups to be viewed or edited.
    """
    queryset = Group.objects.all()
    serializer_class = GroupSerializer
    permission_classes = [permissions.IsAuthenticated]

Note that, as our use case is simple, the views are shared in a ViewSet'. If needed, we can then split the classes intoView`s for more flexibility.

URLs

Now we need to make the routing link to our views. This step is done in the src/tutoapi/urls.py file:

from django.urls import include, path
from rest_framework import routers
from tutoapi.api 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'))
]

With ViewSet, URLs are generated simply by declaring a router.

As noted in the commentary in the code, the api-auth/ path allows the connection features to be used when using the web interface.

Layout

A quick word on layout. The configuration is done globally for the project and mainly defines how many elements will be visible per page.

Below is an extract from the src/tutoapi/settings.py file:

# [...]
REST_FRAMEWORK = {
    'DEFAULT_PAGINATION_CLASS':
        'rest_framework.pagination.PageNumberPagination',
    'PAGE_SIZE':
        10
}
# [...]

The REST_FRAMEWORK parameter should be added to the file. It does not exist when the project is created.

Parameters

We still have one last action to take, declaring that we are using `rest_framework' as an application. This is still done in the src/tutoapi/settings.py file (extract) :

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

So, you just need to complete the existing list of INSTALLED_APPS.

Testing

We are finally ready to test our freshly built API! We have two testing possibilities: the command line or the web interface.

In both cases, we have to launch our application. This is done with the following command:

python manage.py runserver 0.0.0.0:8000

Command line

There is a problem that is important to point out with this method. We have to write the password in the command line. This is good for testing but we need to know the risk.

In another terminal, while our site is running, we can make curl calls:

curl -H 'Accept: application/json; indent=4' -u admin:password http://127.0.0.1:8000/users/

The result should be similar to the following:

{
    "count": 1,
    "next": null,
    "previous": null,
    "results": [
        {
            "url": "http://127.0.0.1:8000/users/1/",
            "username": "admin",
            "email": "admin@example.com",
            "groups": []
        }
    ]
}

Web Interface

On the Web, it's simpler, you have to go to your browser on the url of the site: http://localhost:8000/.

Homepage not logged in

By clicking in the top right corner of the window, it is possible to log in, using the administrator account created at the beginning of the tutorial.

Login prompt

Once logged in, a redirection brings us back to the home page but this time we are logged in:

Homepage logged in

Finally, by clicking on the link given in the page to view the users (http://localhost:8000/users/), we visualize the same result as on the command line :

Users

That's it for this discovery of the DRF framework that allows to easily build RESTful APIs in Python.

Sources

{{ message }}

{{ 'Comments are closed.' | trans }}