Aller au contenu principal

Application métier / SaaS / outil interne avec Django DRF

Repères utiles :

info

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 :

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 :

Et idéalement aussi :

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 :

Relire aussi :

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.py porte le vocabulaire métier : profils, demandes, statuts et validation.
  • serializers.py protège les champs que le frontend ne doit pas piloter librement.
  • permissions.py cadre qui peut voir ou traiter une demande.
  • views.py contient les transitions métier importantes : submit, approve, reject.
  • urls.py expose la ressource /api/purchase-requests/ et ses actions métier.
  • admin.py sert 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 alice avec rôle requester
  • un utilisateur manager1 avec rôle manager

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.

success

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.