1. Fonctoinnalités des Middlewares Django
Manipuler les requêtes, c'est-à-dire l'objet HttpRequest transmis aux vues.
Modifier les réponses, c'est-à-dire l'objet HttpResponse retourné par les vues.
2. Les cinq méthodes de middleware
process_request☆
1. process_request
1. Moment d'exécution
Avant la fonction de vue
2. Paramètres
request est le même objet que dans la vue
3. Valeur de retour
Retourne None
Retourne un objet HttpResponse
Ne exécute pas les méthodes process_request des middlewares suivants
Ne exécute pas la vue
Exécute directement la méthode process_response du middleware courant
4. Ordre d'exécution
Suivant l'ordre d'enregistrement
La méthode process_request a un paramètre request, qui est le même objet que celui utilisé dans la fonction de vue.
Elle peut retourner None ou un objet HttpResponse.
Si elle retourne None, le flux normal se poursuit avec le middleware suivant.
Si elle retourne un objet HttpResponse, Django n'exécutera pas les méthodes suivantes ni la vue, mais commencera à exécuter en ordre inverse les méthodes post-vue à partir de ce middleware.
La méthode process_request s'exécute avant la fonction de vue.
Lors de plusieurs middlewares configurés, ils s'exécutent dans l'ordre d'enregistrement dans MIDDLEWARE.
L'objet request est partagé entre tous les middlewares.
Exemple de code :
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import render, HttpResponse
class MonMiddleware(MiddlewareMixin):
def process_request(self, requete):
print("Méthode process_request du middleware 1.", id(requete)) #S'exécute avant la vue
process_view
process_view
1. Moment d'exécution
Après process_request et avant la fonction de vue
2. Paramètres
requete est un objet HttpRequest.
vue_func est la fonction de vue que Django va utiliser.
vue_args est une liste des arguments positionnels passés à la vue.
vue_kwargs est un dictionnaire des arguments de mots-clés passés à la vue.
vue_args et vue_kwargs n'incluent pas le premier paramètre (requete).
3. Valeur de retour
Retourne None pour exécution normale
Retourne un objet response pour sauter les middlewares suivants et la vue
Retourne vue_func(requete) pour exécuter immédiatement la vue puis continuer avec les méthodes post-vue
4. Ordre d'exécution
Suivant l'ordre d'enregistrement
La méthode process_view s'exécute après process_request et avant la fonction de vue.
Lorsque le dernier middleware process_request atteint la correspondance d'URL, il retourne au premier middleware process_view, puis continue séquentiellement jusqu'à la fonction de vue.
Exemple de code :
class MonMiddleware(MiddlewareMixin):
def process_request(self, requete, callback, callback_args, callback_kwargs):
#callback est la fonction de vue
print("Méthode process_request du middleware 1.", id(requete))
def process_response(self, requete, response): :#basé sur la requête/réponse
print("Méthode process_response du middleware 1 !", id(requete)) #Après la vue
return response
def process_view(self, requete, vue_func, vue_args, vue_kwargs):
print("Méthode process_view du middleware 1 !") #Avant la vue, exécution séquentielle
#return vue_func(requete)
process_template_response
process_template_response(déclenché conditionnellement: si la réponse de la vue a une méthode render)
1. Moment d'exécution
Après la fonction de vue, avant process_response
2. Paramètres
3. Valeur de retour
Retourne un objet response
4. Ordre d'exécution
En ordre inverse d'enregistrement, après exécution de tous les process_template_response, la méthode response.render est appelée
process_exception
process_exception(déclenché conditionnellement: en cas d'erreur)
1. Moment d'exécution
Après la fonction de vue, avant process_response
2. Paramètres
exception est l'objet d'erreur
3. Valeur de retour
Retourne None pour ne pas gérer l'erreur, laissant le middleware suivant s'en occuper
Retourne un objet response pour sauter les autres process_exception et exécuter directement tous les process_response
4. Ordre d'exécution
En ordre inverse d'enregistrement
Exemple de code :
class MonMiddleware(MiddlewareMixin):
def process_request(self, requete):
print("Méthode process_request du middleware 1.", id(requete))
def process_response(self, requete, response):
print("Méthode process_response du middleware 1 !", id(requete))
return response
def process_view(self, requete, vue_func, vue_args, vue_kwargs):
print("Méthode process_view du middleware 1 !")
#return vue_func(requete)
def process_exception(self, requete, exception):#déclenché en cas d'erreur
print("Méthode process_exception du middleware 1 !")
# return HttpResponse(exception) #retourne le message d'erreur
process_response☆
process_response
1. Moment d'exécution
Après la fonction de vue
2. requete, response
requete est le même objet que dans la vue
response est l'objet response retourné
3. Valeur de retour
Retourne un objet response
4. Ordre d'exécution
En ordre inverse d'enregistrement
Exemple de code :
class MonMiddleware(MiddlewareMixin):
def process_request(self, requete):
print("Méthode process_request du middleware 1.", id(requete))
def process_response(self, requete, response):
print("Méthode process_response du middleware 1 !", id(requete))
return response
Toutes ces méthodes peuvent retourner None ou un objet HttpResponse. Si None, l'exécution continue selon les règles de Django. Si HttpResponse, cet objet est directement retourné à l'utilisateur.
Lorsqu'un utilisateur envoie une requête, elle traverse tous les middlewares dans l'ordre d'enregistrement via la méthode process_request, atteint finalement la vue, puis revient à travers les middlewares via process_response avant d'être retournée à l'utilisateur.
3. Applications des méthodes de middleware
process_request peut faire quoi ?
- Créer un middleware pour garantir que les données POST sont accessibles dans request.data quelle que soit l'encodage utilisée par le frontend
- Limiter la fréquence d'accès (par exemple: une adresse IP ne peut accéder que 5 fois par minute)
- Authentification (redirection vers la page de connexion si l'utilisateur n'est pas connecté)
- Enregistrement des journaux d'accès utilisateur (IP, heure, chemin d'accès)
process_response peut faire quoi ? (a accès à l'objet response)
- Ajouter des cookies à toutes les réponses (ou à certaines routes)
- Ajouter des en-têtes de réponse à toutes les réponses (ou à certaines routes)
process_view (exécuté après correspondance de route et avant la fonction de vue)
def process_view(self, requete, callback, callback_args, callback_kwargs):
# print(callback)
# print(callback_args)
# print(callback_kwargs)
#Effectuer des actions avant l'exécution de la fonction
res=callback(requete)
#Effectuer des actions après l'exécution de la fonction, similaire à un décorateur
print("Process_view du middleware 1")
return res
process_exception (exécuté en cas d'erreur dans la vue, pour la gestion globale des exceptions)
# Gestion globale des exceptions, retourne des réponses avec code d'erreur 4xx
def process_exception(self, requete, exception):
print(exception)
return render(requete,'erreur.html')
4. Flux d'exécution des middlewares
1. Exécution de toutes les méthodes request jusqu'à atteindre la fonction de vue.
2. Exécution des autres méthodes du middleware.
3. Passage par toutes les méthodes response avant de retourner la réponse au client.
Note : Si un middleware retourne une valeur dans sa méthode request, seule sa méthode response correspondante est exécutée, puis la réponse est retournée à l'utilisateur. Les middlewares suivants ne sont pas exécutés.
5. Étapes pour créer un middleware personnalisé
- Créer une classe qui hérite de MiddlewareMixin #from django.utils.deprecation import MiddlewareMixin
- Implémenter les méthodes nécessaires comme process_request
- Configurer dans settings (l'ordre d'enregistrement est important)
MIDDLEWARE = [
...
'mon_app.mon_middleware.MonMiddleware1',
...
]