Application métier / SaaS / outil interne avec Django DRF
Repères utiles :
- Django DRF LLM Wiki
- SCHEMA
- Comprendre Django
- Comprendre Django REST Framework
- Comment penser une API avec Django DRF
- Les briques de base de Django DRF
- Backend pour application web ou mobile avec Django DRF
- API avec utilisateurs, rôles et permissions avec Django DRF
- Parcours de lecture
- FAQ, erreurs fréquentes et conseils pratiques
Ce tutoriel explique pourquoi Django DRF est particulièrement pertinent pour les applications métier, les SaaS et les outils internes. L'objectif est de comprendre le problème réel de ces produits, la nature de leur logique métier, la place du backend, les erreurs fréquentes et la manière de construire une architecture qui reste saine dans le temps.
1. Introduction
Quand on parle d'application métier, de SaaS ou d'outil interne, on ne parle pas simplement d'“une application avec quelques formulaires”.
On parle souvent d'un système qui doit gérer :
- des données importantes
- des utilisateurs multiples
- des rôles différents
- des workflows
- des validations métier
- des historiques
- des règles de sécurité
- des besoins opérationnels réels
C'est exactement le genre de terrain où Django DRF devient très intéressant.
Pourquoi ? Parce que ce type de produit a rarement besoin d'un backend “minimal pour faire joli”. Il a besoin d'un backend structuré, maintenable et discipliné.
2. Le problème concret à résoudre
Imaginons quelques produits très différents en apparence :
- un outil RH pour gérer des demandes de congés
- un SaaS de gestion commerciale
- un outil interne de suivi d'interventions
- une plateforme de validation documentaire
- une application de gestion de projets ou de tickets
Ces produits n'ont pas forcément la même interface. Mais ils ont très souvent les mêmes difficultés de fond :
- plusieurs utilisateurs interagissent avec les mêmes données
- certaines actions sont autorisées, d'autres non
- les objets ont des statuts et des transitions
- des règles métier doivent être respectées
- il faut garder une cohérence durable
- il faut pouvoir administrer, auditer et corriger
Le vrai problème n'est donc pas seulement “faire une application”. Le vrai problème est de construire un système backend capable de porter un métier.
3. Que veut dire “application métier” exactement ?
Une application métier est une application conçue pour soutenir une activité réelle, avec ses règles, ses contraintes, ses documents, ses étapes et ses responsabilités.
Exemples :
- gestion de clients
- gestion d'opérations
- suivi d'interventions
- gestion de commandes
- validation de dossiers
- approbation de demandes
- supervision d'équipes
Ce genre d'application est rarement purement décoratif. Elle s'inscrit dans un processus réel.
4. Que veut dire “SaaS” dans ce contexte ?
SaaS signifie généralement qu'un logiciel est fourni comme un service, souvent accessible via le web, avec une logique de comptes, d'abonnements, d'organisations ou d'équipes.
Dans ce type de produit, on retrouve très souvent :
- des utilisateurs
- des comptes ou organisations
- des droits d'accès
- une logique de données persistantes
- une nécessité de faire évoluer le produit proprement
Autrement dit, beaucoup de SaaS sont en pratique aussi des applications métier structurées.
5. Que veut dire “outil interne” ?
Un outil interne est un logiciel utilisé à l'intérieur d'une organisation pour supporter le travail réel d'une équipe ou d'un service.
Exemples :
- gestion des demandes internes
- suivi d'incidents
- gestion de dossiers
- opérations support
- reporting opérationnel
- supervision de tâches
L'erreur fréquente est de sous-estimer ce type d'outil sous prétexte qu'il n'est “pas public”. En réalité, un outil interne peut avoir une logique métier très riche et très sensible.
6. Pourquoi Django DRF est si pertinent ici
Django DRF est particulièrement à l'aise pour ce type de projet car il excelle là où ces produits deviennent complexes.
6.1 Il aime les données structurées
Les applications métier vivent rarement dans le vide. Elles manipulent des entités comme :
- clients
- commandes
- projets
- tickets
- employés
- demandes
- contrats
- documents
- validations
- rapports
Django est très fort pour organiser ce type de données grâce à son ORM et à son cadre général.
6.2 Il supporte bien la logique métier durable
Dans ce type de produit, la complexité n'est pas seulement visuelle. Elle est surtout métier.
Exemples :
- une demande ne peut être validée qu'à certaines conditions
- un dossier change de statut selon un workflow précis
- certains champs sont modifiables à une étape mais plus à une autre
- certaines actions dépendent du rôle, du statut et de l'appartenance à une équipe
Django DRF donne un cadre dans lequel cette complexité peut être organisée plus proprement.
6.3 Il gère bien les utilisateurs, rôles et permissions
Les applications métier et SaaS ont très souvent besoin de cela. Or, c'est précisément un terrain naturel pour Django DRF.
Tu retrouves ici directement les sujets abordés dans :
- Backend pour application web ou mobile avec Django DRF
- API avec utilisateurs, rôles et permissions avec Django DRF
6.4 Il favorise la maintenabilité
Un vrai produit métier doit souvent évoluer longtemps. Ce qui paraît “simple” à la version 1 peut devenir dense après quelques mois :
- nouvelles règles
- nouveaux rôles
- nouvelles validations
- nouveaux états métier
- nouveaux besoins d'export ou de supervision
Django DRF est particulièrement rassurant quand cette croissance arrive.
7. Quand utiliser Django DRF pour ce cas
Django DRF est un bon choix si ton projet ressemble à l'une de ces situations :
- il y a plusieurs entités métier avec des relations claires
- il existe des règles de validation non triviales
- il faut gérer des utilisateurs et des droits
- le produit doit durer dans le temps
- plusieurs équipes ou rôles vont utiliser le système
- il y a un besoin de traçabilité ou d'administration
- il existe une vraie couche métier au-dessus des simples CRUD
En pratique, cela couvre une très grande partie des SaaS sérieux et des outils internes réels.
8. Quand Django DRF n'est pas forcément le meilleur choix
Il ne faut pas transformer Django DRF en réponse automatique.
Il peut être moins pertinent si :
- le produit est extrêmement petit et temporaire
- il n'y a presque aucune logique métier
- les données sont très simples et sans réel workflow
- l'architecture serait disproportionnée par rapport au besoin
- tu veux seulement un prototype ultra minimal avec très peu de contraintes
Mais attention : beaucoup de projets pensent être “simples” au départ, puis découvrent rapidement qu'ils ont en réalité un vrai métier à modéliser.
9. Pré-requis
Pour bien profiter de ce tutoriel, il est préférable d'avoir déjà lu ou compris :
- Comprendre Django
- Comprendre Django REST Framework
- Comment penser une API avec Django DRF
- Les briques de base de Django DRF
Et idéalement aussi :
- Backend pour application web ou mobile avec Django DRF
- API avec utilisateurs, rôles et permissions avec Django DRF
10. Vocabulaire indispensable
Logique métier
Ensemble des règles propres au domaine du produit.
Workflow
Suite d'étapes ou d'états qu'un objet peut traverser.
Validation métier
Vérification qui va au-delà du simple type technique. Exemple : un dossier est complet, une commande peut être confirmée, une demande peut être validée.
Traçabilité
Capacité à savoir ce qui a été fait, quand et par qui.
Exploitation
Ensemble des besoins internes liés à la supervision, à la correction, au support et à la maintenance du système.
Outil interne
Application réservée aux équipes d'une organisation.
SaaS
Produit logiciel livré comme un service, souvent multi-utilisateurs et durable.
Back-office
Interface ou ensemble d'outils utilisés pour piloter, corriger ou superviser le produit côté interne.
11. Vision d'ensemble
Dans ce use case, le backend Django DRF n'est pas seulement un moteur de réponses API. Il devient un support opérationnel du métier.
Une bonne manière de le voir est la suivante :
- le frontend montre l'application
- le backend porte les règles
- la base garde l'état durable
- l'admin et les outils internes soutiennent l'exploitation
- les permissions garantissent le bon niveau d'accès
L'idée essentielle est donc :
dans une application métier ou un SaaS, le backend doit refléter le fonctionnement réel du produit, pas seulement exposer des tables.
12. Architecture type
Voici une architecture type simple mais réaliste.
graph TD
A[Frontend utilisateur] --> B[API Django DRF]
H[Interface interne / back-office] --> B
B --> C[Logique métier]
B --> D[Authentification et permissions]
C --> E[Base de données]
C --> F[Services externes optionnels]
B --> G[Admin Django]
12.1 Frontend utilisateur
Il peut être public, semi-public, ou réservé aux clients/utilisateurs finaux.
12.2 Interface interne ou back-office
Elle permet souvent à des rôles internes de :
- surveiller
- corriger
- valider
- assister
- administrer
12.3 API Django DRF
Elle centralise :
- les données
- les règles
- les permissions
- les réponses structurées
12.4 Logique métier
C'est la partie la plus importante. C'est là que vivent les vraies règles du produit.
12.5 Base de données
Elle garde la mémoire durable du système.
12.6 Admin Django
Elle peut jouer un rôle majeur dans les opérations internes, surtout au début ou pour les équipes support.
13. Ce qui rend ce use case plus exigeant qu'une API simple
Une API simple peut parfois se contenter de quelques routes CRUD propres. Une application métier ou un SaaS sérieux a souvent besoin de beaucoup plus :
- transitions d'état
- règles de validation métier
- historique des actions
- rôles multiples
- restrictions fines
- supervision interne
- correction des données
- export, rapports, notifications, suivi
Autrement dit, on passe d'une logique de simple exposition de données à une logique de système organisé autour d'un métier.
14. Construction pas à pas
Voici une manière saine de construire ce type de backend.
Étape 1 — Identifier le langage du métier
Avant tout, il faut savoir comment le métier parle.
Exemples :
- dossier
- intervention
- demande
- validation
- incident
- client
- contrat
- échéance
Si tu ne connais pas ces objets et ces mots, tu risques de construire une architecture technique déconnectée du réel.
Étape 2 — Identifier les entités principales
Une fois le langage clarifié, identifie les objets centraux du système.
Exemples :
- employé
- demande de congé
- approbation
- document justificatif
- commentaire
- historique
Étape 3 — Identifier les workflows
Très souvent, un objet métier change d'état.
Exemple :
- brouillon
- soumis
- en revue
- validé
- rejeté
- archivé
Ce workflow est souvent plus important que la simple notion de CRUD.
Étape 4 — Identifier les acteurs et leurs responsabilités
Qui utilise le système ?
Exemples :
- collaborateur
- manager
- RH
- admin
- support
Chaque acteur n'a pas le même rôle dans le cycle de vie des objets.
Étape 5 — Identifier les validations métier
Il faut distinguer :
- validation technique
- validation métier
Exemple :
- validation technique : le champ existe et a le bon type
- validation métier : la demande est conforme aux règles du processus
Cette distinction est essentielle dans les applications métier.
Étape 6 — Penser les permissions très tôt
Ce point a déjà été approfondi dans API avec utilisateurs, rôles et permissions avec Django DRF. Mais dans un SaaS ou outil interne, il devient encore plus critique.
Questions utiles :
- qui voit quoi ?
- qui modifie quoi ?
- qui valide quoi ?
- qui supervise quoi ?
- qui peut corriger une anomalie ?
Étape 7 — Prévoir la traçabilité
Dans beaucoup de produits métier, il faut pouvoir répondre à des questions comme :
- qui a créé cet objet ?
- qui a validé cette étape ?
- quand le statut a-t-il changé ?
- qui a modifié ce champ sensible ?
Une application sans traçabilité suffisante devient vite difficile à exploiter.
Étape 8 — Prévoir l'exploitation et la supervision
Ne pense pas seulement à l'utilisateur final. Pense aussi à l'équipe qui devra vivre avec le produit.
Exemples de besoins réels :
- corriger une donnée bloquante
- relancer un workflow
- vérifier un historique
- aider un utilisateur en difficulté
- surveiller les états incohérents
Étape 9 — Décider ce qui relève de l'API publique, interne ou admin
Tout n'a pas besoin d'être exposé de la même manière.
Certaines actions peuvent relever :
- du frontend utilisateur
- d'une interface interne
- de l'admin Django
- d'un outil de support
Étape 10 — Concevoir pour l'évolution
Ce type de produit change souvent avec le temps. Donc il faut prévoir :
- nouveaux rôles
- nouvelles étapes métier
- nouvelles validations
- nouveaux écrans
- nouveaux exports
- nouvelles règles de supervision
15. Exemple concret mental
Prenons un exemple simple : un outil interne de gestion de demandes RH.
Ressources principales
- utilisateur
- demande de congé
- justificatif
- validation
- commentaire interne
- historique
Acteurs
- collaborateur
- manager
- RH
- admin
Exemples de règles métier
- un collaborateur crée sa demande
- un manager valide ou rejette la demande de son équipe
- RH supervise certaines anomalies
- une demande validée n'est plus modifiable librement
- certains documents restent visibles seulement pour certains rôles
Tu vois ici que le défi n'est pas juste technique. Le défi consiste à représenter proprement le fonctionnement réel du métier.
16. Ce que le frontend ne doit pas porter seul
Même si le frontend est important, il ne doit pas être l'endroit où vit la vérité du métier.
Le frontend peut :
- guider l'utilisateur
- afficher le bon état
- masquer certaines actions selon le contexte
Mais le backend doit vraiment faire respecter :
- les droits d'accès
- les transitions d'état
- les validations métier
- les restrictions critiques
Sinon, le produit devient fragile.
17. Erreurs fréquentes
Erreur 1 — Traiter l'application métier comme un simple CRUD
C'est l'erreur la plus classique. Un vrai produit métier contient des états, des règles, des exceptions et des parcours.
Erreur 2 — Modéliser trop vite sans comprendre le métier
Si les objets et les flux sont mal compris, les modèles seront bancals.
Erreur 3 — Reporter l'exploitation à plus tard
Beaucoup d'équipes oublient les besoins de support, d'audit, de correction et d'administration jusqu'au moment où cela devient douloureux.
Erreur 4 — Mélanger toute la logique dans des vues géantes
Quand la logique métier grandit, il faut la structurer proprement.
Erreur 5 — Sous-estimer la valeur de l'admin Django
Dans ce type de produit, l'admin peut être extrêmement utile, surtout pour les besoins internes et la supervision.
Erreur 6 — Construire une architecture trop générique trop tôt
Vouloir tout prévoir abstraitement peut rendre le système plus flou qu'utile. Une architecture claire et métier est souvent meilleure.
18. Bonnes pratiques
18.1 Partir du métier réel
Nommer correctement les objets, les rôles et les états.
18.2 Faire exister clairement les workflows
Les transitions d'état doivent être pensées, pas improvisées.
18.3 Gérer la traçabilité tôt
Surtout si le produit a une valeur opérationnelle forte.
18.4 Séparer les responsabilités
- API pour les interactions applicatives
- logique métier pour les règles
- admin ou outils internes pour l'exploitation
18.5 Penser produit long terme
Un SaaS ou outil interne n'est pas juste une V1. Il faut penser l'évolutivité raisonnable.
18.6 Prévoir les besoins internes
Même un produit “orienté client” a souvent besoin d'outils internes forts.
19. Variantes et évolutions possibles
Variante 1 — Outil interne simple
Une seule équipe, peu de rôles, peu d'états.
Variante 2 — SaaS avec plusieurs organisations
Le produit gère plusieurs comptes ou équipes clientes.
Variante 3 — Workflows plus riches
Plusieurs étapes d'approbation, notifications, historiques détaillés.
Variante 4 — Besoins forts de reporting et supervision
L'équipe interne a besoin de dashboards, exports, suivi d'événements, back-office plus riche.
Variante 5 — Produit plus mature
Le système évolue avec plus de rôles, plus de validations, plus de règles, plus d'intégrations.
20. Comment savoir si ton architecture va dans la bonne direction
Tu avances bien si :
- tu peux décrire clairement les objets métier
- tu peux expliquer les workflows
- tu sais qui agit à chaque étape
- les permissions sont cohérentes avec le métier
- la logique importante ne vit pas uniquement dans le frontend
- ton équipe peut comprendre l'architecture sans lire dans tes pensées
21. Résumé final
Django DRF est un très bon choix pour les applications métier, les SaaS et les outils internes lorsque le projet doit gérer :
- des données structurées
- des workflows
- des règles métier
- des rôles multiples
- des validations
- des besoins d'exploitation et de supervision
Sa vraie force dans ce use case est qu'il permet d'organiser proprement la relation entre :
- données
- utilisateurs
- règles
- API
- exploitation interne
L'idée la plus importante à retenir est la suivante :
dans une application métier ou un SaaS, le backend ne sert pas seulement à stocker et renvoyer des données ; il sert à porter la logique opérationnelle du produit.
22. Pour aller plus loin
La suite logique du wiki peut être :
- Application centrée base de données avec Django DRF
- ou Produit avec back-office et admin Django
- ou un futur glossaire sur les notions de workflow, validation métier, audit et traçabilité
Relire aussi :
- Backend pour application web ou mobile avec Django DRF
- API avec utilisateurs, rôles et permissions avec Django DRF
- Comment penser une API avec Django DRF
23. Mini-projet guidé avec code
Pour rendre ce use case concret, on va prendre un exemple très typique d'application métier :
un outil de gestion de demandes d'achat internes
Le but du mini-projet est de permettre :
- à un collaborateur de créer une demande
- de la soumettre à validation
- à un manager ou à la finance de l'approuver ou de la rejeter
- de garder une trace claire de l'état métier de la demande
C'est exactement le type de cas où Django DRF est utile, parce qu'on ne gère pas seulement des objets : on gère un workflow métier.
24. Structure du mini-projet
opsflow/
├── manage.py
├── opsflow/
│ ├── settings.py
│ ├── urls.py
│ └── ...
└── purchases/
├── admin.py
├── models.py
├── serializers.py
├── permissions.py
├── views.py
└── urls.py
Repères utiles avant de lire le code :
models.pyporte le vocabulaire métier : profils, demandes, statuts et validation.serializers.pyprotège les champs que le frontend ne doit pas piloter librement.permissions.pycadre qui peut voir ou traiter une demande.views.pycontient les transitions métier importantes :submit,approve,reject.urls.pyexpose la ressource/api/purchase-requests/et ses actions métier.admin.pysert de poste de contrôle pour inspecter et corriger rapidement le workflow.
25. Implémentation guidée avec code
Étape 1 — Créer le projet et installer DRF
python -m venv .venv
source .venv/bin/activate
pip install django djangorestframework
django-admin startproject opsflow .
python manage.py startapp purchases
Pourquoi ? Parce qu'on veut un projet simple où la vraie valeur vient de la logique métier et des transitions d'état.
Étape 2 — Déclarer DRF et l'app dans settings.py
Dans opsflow/settings.py :
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"rest_framework",
"purchases",
]
REST_FRAMEWORK = {
"DEFAULT_PERMISSION_CLASSES": [
"rest_framework.permissions.IsAuthenticated",
],
"DEFAULT_AUTHENTICATION_CLASSES": [
"rest_framework.authentication.SessionAuthentication",
"rest_framework.authentication.BasicAuthentication",
],
}
Étape 3 — Modéliser le métier
Dans purchases/models.py :
from django.conf import settings
from django.db import models
class EmployeeProfile(models.Model):
ROLE_CHOICES = [
("requester", "Requester"),
("manager", "Manager"),
("finance", "Finance"),
]
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name="employee_profile",
)
role = models.CharField(max_length=20, choices=ROLE_CHOICES)
def __str__(self) -> str:
return f"{self.user} - {self.role}"
class PurchaseRequest(models.Model):
STATUS_CHOICES = [
("draft", "Draft"),
("submitted", "Submitted"),
("approved", "Approved"),
("rejected", "Rejected"),
]
requester = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name="purchase_requests",
)
title = models.CharField(max_length=150)
description = models.TextField()
amount = models.DecimalField(max_digits=10, decimal_places=2)
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default="draft")
submitted_at = models.DateTimeField(null=True, blank=True)
reviewed_at = models.DateTimeField(null=True, blank=True)
reviewed_by = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name="reviewed_purchase_requests",
)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self) -> str:
return self.title
Puis lancer :
python manage.py makemigrations
python manage.py migrate
Pourquoi ? Parce qu'un vrai outil métier repose d'abord sur un langage clair :
- qui demande ?
- quoi ?
- pour combien ?
- dans quel état métier ?
- qui a validé ?
Étape 4 — Créer le serializer
Dans purchases/serializers.py :
from rest_framework import serializers
from .models import PurchaseRequest
class PurchaseRequestSerializer(serializers.ModelSerializer):
requester = serializers.StringRelatedField(read_only=True)
reviewed_by = serializers.StringRelatedField(read_only=True)
class Meta:
model = PurchaseRequest
fields = [
"id",
"requester",
"title",
"description",
"amount",
"status",
"submitted_at",
"reviewed_at",
"reviewed_by",
"created_at",
]
read_only_fields = [
"id",
"requester",
"status",
"submitted_at",
"reviewed_at",
"reviewed_by",
"created_at",
]
Pourquoi ? Parce qu'on ne veut pas laisser le frontend mentir sur le statut, la date de validation ou l'identité du validateur. Ces éléments doivent être contrôlés par le backend.
Étape 5 — Poser une permission simple
Dans purchases/permissions.py :
from rest_framework.permissions import BasePermission
class CanAccessPurchaseRequest(BasePermission):
def has_permission(self, request, view):
return bool(request.user and request.user.is_authenticated)
def has_object_permission(self, request, view, obj):
profile = getattr(request.user, "employee_profile", None)
if not profile:
return False
if profile.role in {"manager", "finance"}:
return True
return obj.requester == request.user
Pourquoi ? Parce qu'un manager n'a pas le même périmètre qu'un simple demandeur. On commence ici à traduire une hiérarchie opérationnelle en logique d'accès.
Étape 6 — Écrire le viewset avec les vraies actions métier
Dans purchases/views.py :
from django.utils import timezone
from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from .models import PurchaseRequest
from .permissions import CanAccessPurchaseRequest
from .serializers import PurchaseRequestSerializer
class PurchaseRequestViewSet(viewsets.ModelViewSet):
serializer_class = PurchaseRequestSerializer
permission_classes = [IsAuthenticated, CanAccessPurchaseRequest]
def get_queryset(self):
profile = getattr(self.request.user, "employee_profile", None)
if profile and profile.role in {"manager", "finance"}:
return PurchaseRequest.objects.select_related(
"requester", "reviewed_by"
).order_by("-created_at")
return PurchaseRequest.objects.filter(
requester=self.request.user
).select_related("requester", "reviewed_by").order_by("-created_at")
def perform_create(self, serializer):
serializer.save(requester=self.request.user)
@action(detail=True, methods=["post"])
def submit(self, request, pk=None):
purchase_request = self.get_object()
if purchase_request.requester != request.user:
return Response(
{"detail": "Seul le demandeur peut soumettre la demande."},
status=status.HTTP_403_FORBIDDEN,
)
if purchase_request.status != "draft":
return Response(
{"detail": "Seule une demande en brouillon peut être soumise."},
status=status.HTTP_400_BAD_REQUEST,
)
purchase_request.status = "submitted"
purchase_request.submitted_at = timezone.now()
purchase_request.save(update_fields=["status", "submitted_at"])
return Response(self.get_serializer(purchase_request).data)
@action(detail=True, methods=["post"])
def approve(self, request, pk=None):
purchase_request = self.get_object()
profile = getattr(request.user, "employee_profile", None)
if not profile or profile.role not in {"manager", "finance"}:
return Response(
{"detail": "Seul un manager ou la finance peut approuver."},
status=status.HTTP_403_FORBIDDEN,
)
if purchase_request.status != "submitted":
return Response(
{"detail": "Seule une demande soumise peut être approuvée."},
status=status.HTTP_400_BAD_REQUEST,
)
purchase_request.status = "approved"
purchase_request.reviewed_at = timezone.now()
purchase_request.reviewed_by = request.user
purchase_request.save(update_fields=["status", "reviewed_at", "reviewed_by"])
return Response(self.get_serializer(purchase_request).data)
@action(detail=True, methods=["post"])
def reject(self, request, pk=None):
purchase_request = self.get_object()
profile = getattr(request.user, "employee_profile", None)
if not profile or profile.role not in {"manager", "finance"}:
return Response(
{"detail": "Seul un manager ou la finance peut rejeter."},
status=status.HTTP_403_FORBIDDEN,
)
if purchase_request.status != "submitted":
return Response(
{"detail": "Seule une demande soumise peut être rejetée."},
status=status.HTTP_400_BAD_REQUEST,
)
purchase_request.status = "rejected"
purchase_request.reviewed_at = timezone.now()
purchase_request.reviewed_by = request.user
purchase_request.save(update_fields=["status", "reviewed_at", "reviewed_by"])
return Response(self.get_serializer(purchase_request).data)
Pourquoi ce code est important ? Parce qu'il montre exactement ce qui distingue une application métier d'un simple CRUD :
- il existe des états
- il existe des transitions autorisées
- certaines actions ne sont possibles qu'à certains moments et pour certains rôles
Étape 7 — Brancher les routes
Dans purchases/urls.py :
from rest_framework.routers import DefaultRouter
from .views import PurchaseRequestViewSet
router = DefaultRouter()
router.register("purchase-requests", PurchaseRequestViewSet, basename="purchase-request")
urlpatterns = router.urls
Dans opsflow/urls.py :
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path("admin/", admin.site.urls),
path("api/", include("purchases.urls")),
]
Étape 8 — Ajouter l'admin Django
Dans purchases/admin.py :
from django.contrib import admin
from .models import EmployeeProfile, PurchaseRequest
admin.site.register(EmployeeProfile)
admin.site.register(PurchaseRequest)
Pourquoi ? Parce que même dans un outil métier, l'admin reste très utile pour corriger rapidement des données, initialiser des comptes ou examiner un workflow bloqué.
26. Vérification guidée
Lancer l'application
python manage.py createsuperuser
python manage.py runserver
Préparer le scénario dans l'admin
Créer :
- un utilisateur
aliceavec rôlerequester - un utilisateur
manager1avec rôlemanager
Créer une demande en brouillon
curl -u alice:password -X POST http://127.0.0.1:8000/api/purchase-requests/ \
-H "Content-Type: application/json" \
-d '{
"title": "Ordinateur portable",
"description": "Besoin d\'un poste pour un nouveau collaborateur.",
"amount": "1499.00"
}'
Soumettre la demande
curl -u alice:password -X POST \
http://127.0.0.1:8000/api/purchase-requests/1/submit/
Approuver côté manager
curl -u manager1:password -X POST \
http://127.0.0.1:8000/api/purchase-requests/1/approve/
Vérifier qu'un demandeur ne peut pas s'auto-approuver
La requête approve exécutée avec alice:password doit renvoyer un 403 Forbidden.
Ce que tu dois observer
- une demande démarre en
draft - elle passe ensuite en
submitted - elle ne peut être approuvée que par certains rôles
- l'identité du validateur est fixée par le backend
- le workflow métier est visible et contrôlable
27. Ce que cet exemple t'apprend vraiment
Cet exemple montre comment DRF est utilisé concrètement dans un outil métier :
- les modèles représentent les objets métier et leurs états
- le serializer protège les champs sensibles
- les actions DRF (
submit,approve,reject) incarnent les transitions de workflow - les permissions cadrent les responsabilités
- l'admin Django sert de poste de contrôle opérationnel
Autrement dit, on ne parle plus seulement de SaaS ou d'outil interne comme d'une catégorie vague : on voit comment un backend porte des règles métier, des validations et un cycle de vie réel.
Si tu comprends bien ce mini-projet, tu commences à penser comme quelqu'un qui conçoit un système opérationnel, pas seulement une API de formulaires.