đ Django REST Framework â Guide Approfondi
Guide IDEOâLab complet pour maĂźtriser la crĂ©ation d'APIs avec DRF.
Introduction & Concepts
Le "Pourquoi ?" : API, REST, Serializer, View, Router.
REST Concepts APIInstallation & Configuration
settings.py, variables .env, configuration globale.
settings.py .env DEFAULT_Serializers (Le CĆur)
ModelSerializer, validation, relations (FK, M2M).
Serializer ModelSerializer ValidationVues & ViewSets
APIView, Generic Views, ModelViewSet, @action.
APIView ViewSet @actionAuth & Permissions
Token, Session, OAuth2, permissions personnalisées.
TokenAuthentication PermissionsRoutage & URLs
SimpleRouter, DefaultRouter, routing imbriqué.
Routers urls.pyPagination & Filtres
PageNumberPagination, django-filter, SearchFilter.
Pagination FilteringCas d'usage : Mini-Blog
Exemple complet de CRUD (Articles + Auteurs).
CRUD ExempleQu'est-ce que Django REST Framework ?
Django REST Framework (DRF) est un **toolkit puissant et flexible** pour construire des API Web avec Django. Il ne remplace pas Django, il s'appuie dessus pour faciliter la création de points d'accÚs (endpoints) qui retournent des données structurées (JSON, XML) au lieu de HTML.
Quel problÚme cela résout-il ?
Django seul est conçu pour le pattern MTV (Model-Template-View) : il récupÚre des données de la BDD et les injecte dans un template HTML. C'est parfait pour les sites web traditionnels.
Aujourd'hui, vous avez besoin de plus :
- Une application mobile (iOS/Android) doit rĂ©cupĂ©rer les mĂȘmes donnĂ©es.
- Un frontend moderne (React, Vue, Angular) doit interagir avec votre backend.
- Un partenaire externe veut se connecter Ă votre service.
Ces clients ne veulent pas de HTML. Ils veulent des **données brutes** (ex: JSON). DRF est la surcouche qui transforme Django en un puissant serveur d'API RESTful.
Les 4 Piliers de DRF
1. Serializers (Sérialiseurs)
C'est le cĆur de DRF. Ils font la **traduction** dans les deux sens :
- Objet Python/ModÚle Django -> JSON : Pour l'envoyer au client (Sérialisation).
- JSON -> Objet Python/ModÚle Django : Pour valider et enregistrer les données reçues du client (Désérialisation).
2. Vues (Views / ViewSets)
C'est la **logique mĂ©tier**. La vue reçoit une requĂȘte (ex: GET /api/articles/1), utilise le Serializer pour rĂ©cupĂ©rer et formater l'article, et le renvoie en JSON.
DRF fournit des vues génériques (APIView, ModelViewSet) qui gÚrent 90% du travail d'un CRUD (Create, Read, Update, Delete) pour vous.
3. Routers (Routeurs)
Le routeur génÚre **automatiquement** les URLs pour vos ViewSets. Vous n'avez pas besoin de définir manuellement les URLs pour `list`, `detail`, `create`, `update`, etc. Le routeur s'en charge.
4. Authentification & Permissions
DRF étend le systÚme d'authentification de Django pour les APIs. Il gÚre l'authentification par Token, par Session, OAuth, etc. Les **Permissions** définissent qui a le droit de faire quoi (ex: `IsAuthenticated`, `IsAdminUser`, ou des permissions personnalisées).
Quand utiliser DRF ?
Utilisez DRF si :
- Votre backend doit servir de données à un **frontend séparé** (React, Vue, Angular).
- Vous construisez une **application mobile** qui a besoin d'un backend.
- Vous exposez une **API publique** ou privée pour des partenaires.
- Vous voulez standardiser la communication entre microservices.
Quand est-ce *overkill* ?
N'utilisez pas DRF (ou une API) si :
- Votre projet est un **site web 100% traditionnel** (ex: blog, site vitrine) oĂč Django rend tous les templates HTML.
- Vous avez juste besoin de 1 ou 2 "endpoints" simples. Une vue Django classique retournant un
JsonResponsepeut suffire.
Alternatives Populaires
1. Django-Ninja
- Approche : "API-first", trĂšs moderne, s'inspire de FastAPI.
- Avantage : Utilise la **validation de type Pydantic** (trÚs puissant) et génÚre automatiquement une documentation OpenAPI (Swagger/Redoc) de haute qualité.
- Inconvénient : Moins mature que DRF, écosystÚme plus petit.
2. FastAPI (Framework Python, pas Django)
- Approche : Un micro-framework Python dédié aux APIs, basé sur Starlette et Pydantic.
- Avantage : ExtrĂȘmement rapide (performance asynchrone), validation de type intĂ©grĂ©e, documentation auto.
- Inconvénient : N'inclut pas l'écosystÚme Django (pas d'Admin, pas d'ORM Django, pas de systÚme d'authentification complet par défaut).
DRF vs. Ninja : Lequel choisir ?
En 2025, le choix se résume souvent à :
- Prenez DRF : Si vous avez un **projet Django existant** à transformer en API, ou si vous tenez à l'écosystÚme d'addons de DRF (ex: `drf-spectacular`, `djoser`). C'est le choix le plus robuste et testé.
- Prenez Django-Ninja : Si vous démarrez un **nouveau projet Django** et que votre priorité absolue est la **performance** et la **documentation OpenAPI** automatique.
Installation (Python venv)
# S'assurer que le venv est activé # source venv/bin/activate pip install djangorestframework pip install markdown # Requis pour l'API "Browsable" pip install django-filter # Requis pour le filtrage
Ajout Ă settings.py
Ajoutez 'rest_framework' à vos applications installées.
# settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Apps tierces
'rest_framework',
'rest_framework.authtoken', # Pour l'authentification par Token
'django_filters', # Pour le filtrage
# Vos apps
'core',
'accounts',
]Configuration Globale de DRF
Toutes les configurations globales de DRF se font dans un dictionnaire REST_FRAMEWORK dans votre settings.py.
Voici une configuration de **départ solide** et sécurisée pour la plupart des projets :
# settings.py
REST_FRAMEWORK = {
# --- AUTHENTIFICATION ---
# Par défaut : Token (pour scripts/apps) et Session (pour l'API browsable)
'DEFAULT_AUTHENTICATION_CLASSES': [
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
],
# --- PERMISSIONS ---
# Politique par défaut : Tout est fermé, sauf si authentifié.
# (Alternative : IsAuthenticatedOrReadOnly pour autoriser lecture)
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
],
# --- PAGINATION ---
# Active la pagination globale pour toutes les listes
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 25, # Nombre d'items par page
# --- FILTRAGE ---
'DEFAULT_FILTER_BACKENDS': [
'django_filters.rest_framework.DjangoFilterBackend',
'rest_framework.filters.SearchFilter',
'rest_framework.filters.OrderingFilter',
],
# --- SCHĂMA & DOCS ---
# Utilise drf-spectacular (à installer) pour générer OpenAPI 3.0
# 'DEFAULT_SCHEMA_CLASS': 'drf_spectacular.openapi.AutoSchema',
}Sécurité : Ne jamais coder en dur !
Votre configuration REST_FRAMEWORK ne doit pas contenir de clés secrÚtes. Cependant, d'autres paramÚtres (comme ceux pour Sentry ou les BDD) le feront.
Utilisez toujours des variables d'environnement (via python-dotenv).
Exemple avec .env
# .env (Ă la racine du projet, dans .gitignore) DJANGO_SECRET_KEY="votre-secret-key-ici" DJANGO_DEBUG=True SENTRY_DSN="https://..."
Utilisation dans settings.py
# settings.py
from dotenv import load_dotenv
import os
load_dotenv() # Charge le fichier .env
SECRET_KEY = os.getenv("DJANGO_SECRET_KEY")
DEBUG = os.getenv("DJANGO_DEBUG", "False") == "True"
# Exemple de configuration de Sentry (addon populaire)
import sentry_sdk
from sentry_sdk.integrations.django import DjangoIntegration
SENTRY_DSN = os.getenv("SENTRY_DSN")
if SENTRY_DSN:
sentry_sdk.init(
dsn=SENTRY_DSN,
integrations=[DjangoIntegration()],
traces_sample_rate=0.2,
)
Ajout des URLs de base
Pour utiliser l'API "Browsable" et l'authentification par Token, vous devez ajouter quelques URLs au fichier urls.py principal de votre projet.
# ideolab_site/urls.py
from django.contrib import admin
from django.urls import path, include
from rest_framework.authtoken import views as authtoken_views
urlpatterns = [
path('admin/', admin.site.urls),
# --- URLs de base DRF ---
# 1. URLs de l'API (ex: /api/v1/)
# On délÚgue toutes nos URLs d'API à un fichier séparé
path('api/v1/', include('core.api_urls')), # 'core' est un exemple d'app
# 2. API "Browsable" (Login / Logout)
# Requis pour pouvoir se connecter/déconnecter de l'interface web
path('api-auth/', include('rest_framework.urls')),
# 3. Authentification par Token
# Permet Ă un client de faire un POST avec 'username' et 'password'
# pour obtenir un Token en retour.
path('api-token-auth/', authtoken_views.obtain_auth_token),
# ... vos autres urls ...
]ModelSerializer
[...Contenu détaillé sur le ModelSerializer...]
[...Exemple de code pour un ArticleSerializer...]
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ('id', 'title', 'content', 'author', 'created_at')
read_only_fields = ('author',)Validation
[...Contenu détaillé sur la validation de champ (validate_field) et la validation d'objet (validate)...]
[...Exemple de code pour valider un titre...]
def validate_title(self, value):
if "Django" not in value:
raise serializers.ValidationError("Le titre doit contenir 'Django'")
return valueRelations (Foreign Key, ManyToMany)
[...Contenu détaillé sur PrimaryKeyRelatedField, StringRelatedField, Nested Serializers et SlugRelatedField...]
Champs Avancés
[...Contenu détaillé sur SerializerMethodField, ReadOnlyField, et comment gérer l'écriture (write-only)...]
PiĂšges & Bonnes Pratiques
[...Contenu détaillé sur le problÚme N+1 (select_related, prefetch_related) et la gestion des champs "write-only" (ex: mot de passe)...]
APIView
[...Contenu détaillé sur APIView, quand l'utiliser (logique complexe, endpoints non-CRUD)...]
Vues Génériques (ListCreateAPIView, RetrieveUpdateDestroyAPIView)
[...Contenu détaillé sur les vues génériques, un bon compromis entre APIView et ViewSets...]
ModelViewSet
[...Contenu détaillé sur ModelViewSet, le moyen le plus rapide de créer un CRUD complet. Définition de queryset et serializer_class...]
[...Exemple de code ArticleViewSet...]
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
permission_classes = [IsAuthenticated, IsAuthorOrReadOnly]Actions Personnalisées (@action)
[...Contenu détaillé sur l'ajout d'endpoints personnalisés à un ViewSet (ex: /api/articles/1/publish/)...]
[...Exemple de code pour @action(detail=True)...]
Token vs Session
[...Contenu dĂ©taillĂ© sur le choix du backend. TokenAuthentication pour les clients lourds/mobiles, SessionAuthentication pour les frontends web (SPA) sur le mĂȘme domaine (sĂ©curitĂ© CSRF)...]
Permissions Incluses
[...Contenu détaillé sur IsAuthenticated, IsAdminUser, IsAuthenticatedOrReadOnly, AllowAny...]
Permissions Personnalisées
[...Contenu détaillé sur la création d'une permission personnalisée en héritant de BasePermission et en surchargeant has_object_permission()...]
[...Exemple de permission IsAuthorOrReadOnly...]
JWT & OAuth2
[...Contenu détaillé sur les alternatives au Token simple. Présentation de Simple-JWT et Django-OAuth-Toolkit...]
SimpleRouter vs DefaultRouter
[...Contenu détaillé. DefaultRouter inclut l'endpoint racine (l'API Browsable), SimpleRouter ne le fait pas. 99% du temps, utilisez DefaultRouter...]
Configuration
[...Contenu détaillé sur la création d'un fichier `api_urls.py` dans une app, et comment l'inclure dans le `urls.py` principal...]
[...Exemple de code pour un router.register()...] from rest_framework.routers import DefaultRouter from . import views router = DefaultRouter() router.register(r'articles', views.ArticleViewSet, basename='article') router.register(r'users', views.UserViewSet, basename='user') urlpatterns = router.urls
Routage Imbriqué
[...Contenu détaillé sur la création d'URLs imbriquées (ex: /api/articles/1/comments/2/) avec `drf-nested-routers`...]
Pagination
[...Contenu détaillé sur PageNumberPagination (globale vs. par vue) et CursorPagination (pour les feeds infinis)...]
Filtrage (django-filter)
[...Contenu détaillé sur l'utilisation de `django-filter` pour permettre des filtres sur les query params (ex: /api/articles/?author=1&published=true)...]
Recherche & Ordre
[...Contenu détaillé sur `SearchFilter` (/?search=...) et `OrderingFilter` (/?ordering=-created_at)...]
models.py
[...ModĂšle Article (avec FK vers User) et ModĂšle Commentaire (avec FK vers Article et User)...]
serializers.py
[...ArticleSerializer (avec `author` en `ReadOnlyField`) et CommentSerializer...]
views.py
[...ArticleViewSet (avec permission `IsAuthorOrReadOnly`) et CommentViewSet (avec permission `IsOwnerOrReadOnly`). Surcharge de `perform_create` pour lier l'auteur...]
api_urls.py
[...Utilisation de `drf-nested-routers` pour avoir /api/articles/<id>/comments/...]
