Funktionsweise und Erstellung von benutzerdefinierten Django-Dekoratoren
Dekoratoren sind leistungsstarke Werkzeuge in Django, mit denen Sie gemeinsam genutzte Logik einfach zu View-Funktionen oder -Klassen hinzufügen können. In diesem Artikel erkläre ich Ihnen schrittweise die Funktionsweise und die Erstellungsweise von Dekoratoren, damit Sie in der Lage sind, Ihre eigenen benutzerdefinierten Dekoratoren zu schreiben.
1. Was ist ein Dekorator?
Ein Dekorator ist eine höherwertige Funktion in Python. Das bedeutet, dass er eine Funktion als Argument entgegennimmt und innerhalb von ihr eine neue Funktion zurückgibt.
- Rolle des Dekorators:
- Er kann eine Funktion umfassen, um bestimmte Funktionalität hinzuzufügen oder zu ändern.
- Er macht den Code wiederverwendbar und bündig.
2. Grundlegende Funktionsweise von Dekoratoren
Um die Funktionsweise von Dekoratoren zu verstehen, betrachten wir ein einfaches Beispiel.
def simple_decorator(func):
def wrapper():
print("Bevor die Funktion ausgeführt wird")
func()
print("Nachdem die Funktion ausgeführt wurde")
return wrapper
@simple_decorator
def say_hello():
print("Hallo!")
say_hello()
Ausgabe:
Bevor die Funktion ausgeführt wird
Hallo!
Nachdem die Funktion ausgeführt wurde
Erklärung:
@simple_decorator
übergibt die Funktionsay_hello
an die Funktionsimple_decorator
.simple_decorator
erzeugt intern eine neue Funktionwrapper
und gibt sie zurück.- Wenn
say_hello
aufgerufen wird, wird anstelle der ursprünglichen Funktionwrapper
ausgeführt. - Im Inneren der
wrapper
-Funktion werden zusätzliche Aktionen (Drucknachricht) ausgeführt und die ursprüngliche Funktion wird aufgerufen.
3. Prinzipien zur Erstellung benutzerdefinierter Dekoratoren in Django
Um Dekoratoren in Django zu erstellen, müssen Sie mit dem Request-Objekt der View-Funktion umgehen können. Damit können Sie je nach bestimmten Bedingungen HTTP-Antworten manipulieren oder Logik ausführen.
4. Schritt-für-Schritt-Struktur zur Erstellung eines benutzerdefinierten Dekorators
Hier ist die grundlegende Struktur zur Erstellung eines benutzerdefinierten Dekorators in Django:
functools.wraps
verwenden: Verwenden Sie@wraps
, um Metadaten wie den Namen der ursprünglichen Funktion und die Dokumentationszeichenfolgen beizubehalten.- Logik basierend auf
request
hinzufügen: Schreiben Sie Logik, um das Request-Objekt zu analysieren oder zu validieren. - Die ursprüngliche Funktion aufrufen oder eine alternative Antwort zurückgeben: Sie können die Aufrufe der ursprünglichen Funktion unter bestimmten Bedingungen blockieren und andere Antworten zurückgeben.
Hier ist ein Beispielcode:
from functools import wraps
from django.http import HttpResponseForbidden
def custom_decorator(view_func):
@wraps(view_func)
def _wrapped_view(request, *args, **kwargs):
# Überprüfen Sie Benutzerinformationen im Request-Objekt
if not request.user.is_authenticated:
return HttpResponseForbidden("Sie müssen eingeloggt sein, um auf diese Seite zuzugreifen.")
# Rufe die ursprüngliche View-Funktion auf
return view_func(request, *args, **kwargs)
return _wrapped_view
5. Wie fügt man Parameter zu einem Dekorator hinzu?
Wenn ein Dekorator Parameter annehmen soll, muss eine zweiseitige Funktionsstruktur verwendet werden. Der Grund dafür ist, dass die erste Funktion verwendet wird, um die Parameter des Dekorators zu behandeln, während die zweite Funktion das tatsächliche Verpacken der View-Funktion übernimmt.
Gr Grundstruktur:
def decorator_with_params(param1, param2):
def actual_decorator(view_func):
@wraps(view_func)
def _wrapped_view(request, *args, **kwargs):
# Logik unter Verwendung der Parameter param1 und param2
return view_func(request, *args, **kwargs)
return _wrapped_view
return actual_decorator
Erklärung:
- Die erste Funktion
decorator_with_params
behandelt die Parameter des Dekorators (param1
,param2
). - Sie gibt die Dekoratorfunktion (
actual_decorator
) zurück, die die tatsächliche View-Funktion umschließt. - Innerhalb von
actual_decorator
wird die ursprüngliche View-Funktion aufgerufen oder zusätzliche Logik ausgeführt.
6. Praktisches Beispiel: Zeitbeschränkungs-Dekorator
Hier ist ein Beispiel für einen Dekorator, der nur zu bestimmten Zeiten zugänglich ist. Dieser Dekorator verarbeitet erlaubte Zeitspannen als Parameter.
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("Diese Seite ist nur zu bestimmten Zeiten zugänglich.")
return view_func(request, *args, **kwargs)
return _wrapped_view
return decorator
@time_restricted_access(9, 17) # Erlaubt von 9 Uhr bis 17 Uhr
def working_hours_view(request):
return render(request, 'working_hours.html')
Funktionsweise Erklärung:
time_restricted_access
ist die erste Funktion, die die Parameter (start_hour
,end_hour
) verarbeitet.- Die erste Funktion gibt intern die Dekoratorfunktion zurück, die die View umschließt.
- Die Dekoratorfunktion akzeptiert den
request
und prüft die aktuelle Stunde (datetime.now().hour
) und je nach zeitlichen Kriterien:- Wenn die Bedingungen erfüllt sind, wird die View aufgerufen und das Ergebnis zurückgegeben.
- Wenn die Bedingungen nicht erfüllt sind, wird der Zugang mit
HttpResponseForbidden
blockiert.
Warum müssen Funktionen zweimal umschlossen werden?
Die Funktionen müssen zweimal umschlossen werden, um die Rollen der Parameterverarbeitung und der View-Funktionsverarbeitung zu trennen.
- Die erste Funktion: Nimmt die Parameter (
start_hour
,end_hour
) entgegen und generiert intern den Dekorator. - Die zweite Funktion: Der generierte Dekorator umschließt die View-Funktion und funktioniert basierend auf der Anfrage.
Diese Struktur macht Dekoratoren flexibel und wiederverwendbar.
7. Verwendung in Klassenbasierten Views (CBV)
Für klassenbasierte Views müssen Sie method_decorator
verwenden.
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. Fazit: Hinweise zur Erstellung benutzerdefinierter Dekoratoren
- Einfachheit bewahren: Die Logik des Dekorators sollte einfach und klar sein.
- Wiederverwendbarkeit berücksichtigen: Wenn bestimmte Logik in mehreren Views verwendet wird, extrahieren Sie sie in einen Dekorator.
- Parameterverarbeitung: Verwenden Sie die zweiseitige Struktur, wenn Parameter erforderlich sind.
- Metadaten bewahren: Verwenden Sie
@wraps
, um die Metadaten der ursprünglichen Funktion beizubehalten.
Schlussfolgerung
Jetzt haben Sie verstanden, wie benutzerdefinierte Dekoratoren in Django funktionieren und sind in der Lage, solche zu erstellen, die Parameter entgegennehmen. Nutzen Sie diesen Artikel, um Dekoratoren zu schreiben, die zu Ihrem Projekt passen!
Add a New Comment