Le principe de fonctionnement et la rédaction de décorateurs personnalisés Django
Les décorateurs sont des outils puissants qui vous permettent d'ajouter facilement une logique commune à des fonctions ou classes de vue dans Django. Dans cet article, nous expliquerons étape par étape le principe de fonctionnement et la méthode de rédaction des décorateurs, afin de vous aider à créer vos propres décorateurs personnalisés.
1. Qu'est-ce qu'un décorateur ?
Un décorateur est une fonction d'ordre supérieur en Python. Cela signifie qu'il s'agit d'une fonction qui prend une fonction en argument et retourne une nouvelle fonction à l'intérieur.
- Rôle du décorateur :
- Il enveloppe une fonction pour ajouter ou modifier une fonctionnalité.
- Il rend le code réutilisable et concis.
2. Le principe de fonctionnement de base des décorateurs
Pour comprendre le principe de fonctionnement des décorateurs, examinons un exemple simple.
def simple_decorator(func):
def wrapper():
print("Avant l'exécution de la fonction")
func()
print("Après l'exécution de la fonction")
return wrapper
@simple_decorator
def say_hello():
print("Bonjour!")
say_hello()
Résultat de la sortie :
Avant l'exécution de la fonction
Bonjour!
Après l'exécution de la fonction
Explication :
@simple_decorator
passe la fonctionsay_hello
à la fonctionsimple_decorator
.simple_decorator
crée et retourne une nouvelle fonctionwrapper
.- Lorsque
say_hello
est appelée, c'estwrapper
qui est exécuté à la place de la fonction d'origine. - Le code à l'intérieur de la fonction
wrapper
exécute des actions supplémentaires (messages d'impression) et appelle la fonction d'origine.
3. Le principe de création de décorateurs personnalisés dans Django
Pour créer un décorateur dans Django, il est nécessaire de savoir manipuler l'objet request, qui est un argument de la fonction de vue. Sur cette base, vous pouvez manipuler les réponses HTTP ou exécuter des logiques en fonction de certaines conditions.
4. Structure d'étape par étape pour créer un décorateur personnalisé
Voici la structure de base pour créer un décorateur personnalisé dans Django :
- Utiliser
functools.wraps
: utilisez@wraps
pour conserver les métadonnées telles que le nom de la fonction d'origine et la chaîne de documentation. - Ajouter de la logique basée sur
request
: créez une logique pour analyser ou valider l'objet de requête. - Appeler la fonction d'origine ou retourner une réponse de substitution : il peut être nécessaire de bloquer l'appel à la fonction d'origine et de retourner une réponse différente en fonction de certaines conditions.
Voici un exemple de code :
from functools import wraps
from django.http import HttpResponseForbidden
def custom_decorator(view_func):
@wraps(view_func)
def _wrapped_view(request, *args, **kwargs):
# Vérifier les informations de l'utilisateur dans l'objet request
if not request.user.is_authenticated:
return HttpResponseForbidden("Vous devez être connecté pour accéder à cette page.")
# Appeler la fonction de vue d'origine
return view_func(request, *args, **kwargs)
return _wrapped_view
5. Comment ajouter des paramètres à un décorateur ?
Si un décorateur doit recevoir des paramètres, il faut utiliser une structure à deux niveaux d'enveloppement. Cela est nécessaire car la première fonction est utilisée pour traiter les paramètres du décorateur, tandis que la seconde fonction enveloppe la fonction de vue réelle.
Structure de base :
def decorator_with_params(param1, param2):
def actual_decorator(view_func):
@wraps(view_func)
def _wrapped_view(request, *args, **kwargs):
# Logique utilisant les paramètres param1, param2
return view_func(request, *args, **kwargs)
return _wrapped_view
return actual_decorator
Explication :
- La première fonction
decorator_with_params
traite les paramètres du décorateur (param1
,param2
). - Elle retourne la fonction décorateur qui enveloppe la fonction de vue réelle.
- À l'intérieur de
actual_decorator
, la fonction de vue d'origine est appelée ou une logique supplémentaire est exécutée.
6. Exemple pratique : Décorateur avec restriction horaire
Voici un exemple de décorateur qui ne permet l'accès que durant certaines heures. Ce décorateur prend en paramètres les heures autorisées.
from datetime import datetime
from django.http import HttpResponseForbidden
def time_restricted_access(start_hour, end_hour):
def decorator(view_func):
@wraps(view_func)
def _wrapped_view(request, *args, **kwargs):
current_hour = datetime.now().hour
if not (start_hour <= current_hour < end_hour):
return HttpResponseForbidden("Cette page est accessible uniquement à certaines heures.")
return view_func(request, *args, **kwargs)
return _wrapped_view
return decorator
@time_restricted_access(9, 17) # Autorisé de 9h à 17h
def working_hours_view(request):
return render(request, 'working_hours.html')
Explication du fonctionnement :
time_restricted_access
est la première fonction qui traite les paramètres (start_hour
,end_hour
).- Elle retourne la fonction décorateur qui enveloppe la vue.
- La fonction décorateur reçoit
request
et vérifie l'heure actuelle (datetime.now().hour
) pour appliquer des conditions horaires : - Si les conditions sont satisfaites, elle appelle la vue et retourne le résultat.
- Si les conditions ne sont pas satisfaites, elle bloque l'accès avec
HttpResponseForbidden
.
Pourquoi faut-il envelopper la fonction deux fois ?
La nécessité d'envelopper la fonction deux fois est de séparer le traitement des paramètres et le traitement de la fonction de vue.
- La première fonction : elle reçoit les paramètres (
start_hour
,end_hour
) et crée le décorateur en interne. - La seconde fonction : elle enveloppe la fonction de vue créée et agit sur la requête.
Cette structure rend le décorateur flexible et réutilisable.
7. Utiliser avec des vues basées sur des classes (CBV)
Pour les vues basées sur des classes, vous devez utiliser method_decorator
.
from django.utils.decorators import method_decorator
from django.views import View
@method_decorator(time_restricted_access(9, 17), name='dispatch')
class MyView(View):
def get(self, request):
return render(request, 'my_template.html')
8. Conclusion : Points à considérer lors de la création d'un décorateur personnalisé
- Rester simple : la logique du décorateur doit être simple et claire.
- Considérer la réutilisabilité : si une certaine logique est utilisée dans plusieurs vues, envisagez de l'extraire dans un décorateur.
- Traitement des paramètres : en cas de besoin de paramètres, utilisez une structure à deux niveaux d'enveloppement.
- Conservation des métadonnées : utilisez
@wraps
pour conserver les métadonnées de la fonction d'origine.
Finalement
Vous comprenez maintenant le principe de fonctionnement des décorateurs personnalisés dans Django et êtes capable de créer des décorateurs qui acceptent des paramètres. Utilisez cet article pour rédiger des décorateurs adaptés à votre projet !
Add a New Comment