DjangoRF

Découverte de Django REST Framework

Pour des besoins personnels, je me suis intéressé au développement d'API REST en Django. J'ai alors découvert Django REST framework, aussi appelé DRF. Voici donc une introduction à ce framework.

Comme indiqué sur le site officiel, Django REST framework est un outil puissant et flexible qui permet de créer des APIs web. C'est exactement ce que nous allons faire !

Django dans un container Docker

Par choix, nous allons monter ce test dans un container Docker basique. Pour commencer, nous avons besoin d'un fichier Dockerfile qui va nous permettre de créer notre image. Voici le contenu de ce fichier :

FROM python:3.8

# Setup env vars
ENV PYTHONBUFFERED 1
ENV PYTHONPATH /app

# Add arg for package installation
ARG DEBIAN_FRONTEND=noninteractive

# 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:8000" ]

Quelques explications s'imposent. Nous partons d'une image python en version 3.8 pour ne pas avoir à réinventer la roue. L'installation des packages se fait à l'aide du fichier requirements.txt, présent à la racine du projet. Pour notre exemple, il contient les lignes suivantes :

Django==3.0.5
djangorestframework==3.11.0

Le code source est présent dans le dossier src/, vide pour l'instant.

Il est temps de construite notre image Docker. Cela se fait avec la commande suivante :

docker build -t tutoapi:0.0.1 .

C'est une bonne pratique de spécifier un tag pour l'image, ici 0.0.1.

Initialisation du projet

Il nous faut à présent nous connecter au container pour créer notre projet. Afin de réaliser cette étape, nous allons monter dans le conteneur le dossier du projet. Sous Linux, la commande à lancer est la suivante :

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

L'appli se lance sur le port 8000 (http://localhost:8000).

Django start page

Dernière étape préliminaire avant de rentrer dans le vif du sujet, créons un administrateur pour notre site :

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

Découverte de DRF

Nous sommes désormais fin prêts pour débuter sur Django REST Framework !

Sérialiseurs

En premier lieu, nous devons définir des sérialiseurs pour modéliser nos objets. Le fichier src/tutoapi/api/serializers.py (fichier à créer) contient le code suivant :

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

Ici nous nous basons sur deux modèles Django, User et Group.

En lien avec chaque modèle, une classe "sérialiseur" est déclarée. Elle déclare également les champs qui nous intéressent.

Vues

Il faut désormais déclarer des vues pour nos interagir avec nos objets. Cela se fait dans le fichier src/tutoapi/api/views.py :

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]

Remarquons que, comme notre cas d'usage est simple, les vues sont mutualisées dans un ViewSet. Si besoin, nous pourrons ensuite découper les classes en View afin d'obtenir plus de flexibilité.

URLs

Nous devons désormais faire le lien de routage vers nos vues. Cette étape est réalisée dans le fichier src/tutoapi/urls.py :

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

Grâce aux ViewSet, la génération des URLs se fait simplement en déclarant un routeur.

Comme indiqué en commentaire dans le code, le chemin api-auth/ permet d'utiliser les fonctionnalités de connexion lors de l'utilisation de l'interface Web.

Mise en page

Un mot rapide sur la mise en page. La configuration se fait globalement pour le projet et permet de définir principalement combien d'éléments seront visibles par page.

Ci-dessous, l'extrait du fichier src/tutoapi/settings.py :

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

Le paramètre REST_FRAMEWORK est à ajouter dans le fichier. Il n'existe pas à la création du projet.

Paramètres

Il nous reste une dernière action à réaliser, déclarer que nous utilisons rest_framework comme application. Cela se fait encore dans le fichier src/tutoapi/settings.py (extrait) :

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

Il suffit donc de compléter la liste déjà existante des INSTALLED_APPS.

Tests

Nous sommes enfin prêts à tester notre API fraîchement construite ! Deux possibilités de tests s'offrent à nous : la ligne de commande ou bien l'interface Web.

Dans les deux cas, nous devons lancer notre application. Cela se fait avec la commande suivante :

python manage.py runserver 0.0.0.0:8000

Ligne de commande

Il existe un problème qu'il est important de souligner avec cette méthode. Nous devons écrire le mot de passe dans la ligne de commande. C'est bien pour faire des tests mais il faut néanmoins connaître le risque.

Dans un autre terminal, pendant que notre site tourne, nous pouvons faire des appels curl :

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

Le résultat obtenu devrait être similaire à ce qui suit :

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

Interface Web

En Web, c'est plus simple, il faut se rendre dans son navigateur sur l'url du site : http://localhost:8000/

Homepage not logged in

En cliquant en haut à droite de la fenêtre, il est possible de se connecter, en utilisant le compte administrateur créé au début du tutoriel.

Login prompt

Une fois connecté, une redirection nous ramène sur la page d'accueil mais cette fois-ci nous sommes connectés :

Homepage logged in

Enfin, en cliquant sur le lien donné dans la page pour visualiser les utilisateurs (http://localhost:8000/users/), nous visualisons le même résultat qu'en ligne de commande :

Users

Voilà, c'est tout pour cette découverte du framework DRF qui permet facilement de construite des API RESTful en Python.

Sources

{{ message }}

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