De werking en het schrijven van aangepaste Django-decorators
Decorators zijn krachtige hulpmiddelen in Django die het mogelijk maken om eenvoudig gemeenschappelijke logica toe te voegen aan view-functies of -klassen. In dit artikel beschrijven we stap voor stap de werking en het schrijven van decorators, zodat je zelf aangepaste decorators kunt maken.
1. Wat is een decorator?
Een decorator is een hogere-orde functie in Python. Met andere woorden, het is een functie die een andere functie als argument neemt en een nieuwe functie retourneert.
- De rol van een decorator:
- Het kan een functie omhullen om specifieke functionaliteit toe te voegen of te wijzigen.
- Het maakt de code herbruikbaar en beknopt.
2. Basiswerking van decorators
Laten we een eenvoudig voorbeeld bekijken om de werking van decorators te begrijpen.
def simple_decorator(func):
def wrapper():
print("Voor de functie draait")
func()
print("Na de functie draait")
return wrapper
@simple_decorator
def say_hello():
print("Hallo!")
say_hello()
Uitvoer:
Voor de functie draait
Hallo!
Na de functie draait
Uitleg:
@simple_decorator
geeft de functiesay_hello
door aan de functiesimple_decorator
.simple_decorator
creëert en retourneert een nieuwewrapper
functie intern.- Wanneer
say_hello
wordt aangeroepen, wordt de originele functie vervangen doorwrapper
. - De
wrapper
functie voert extra acties (afdrukberichten) uit en roept de originele functie aan.
3. De principes voor het schrijven van aangepaste decorators in Django
Om decorators in Django te schrijven, moet je de request-objecten van de view-functie kunnen beheren. Op basis hiervan kun je HTTP-responsen manipuleren of logica uitvoeren onder bepaalde voorwaarden.
4. Stapsgewijze structuur voor het schrijven van een aangepaste decorator
Hier is de basisstructuur voor het schrijven van een aangepaste decorator in Django:
functools.wraps
gebruiken: gebruik@wraps
om metadata zoals de naam van de originele functie en docstring te behouden.- Logica toevoegen op basis van
request
: schrijf logica voor het analyseren of valideren van het request-object. - De originele functie aanroepen of een alternatieve respons retourneren: op basis van bepaalde voorwaarden kun je het aanroepen van de originele functie blokkeren en een andere respons retourneren.
Hier is een voorbeeldcode:
from functools import wraps
from django.http import HttpResponseForbidden
def custom_decorator(view_func):
@wraps(view_func)
def _wrapped_view(request, *args, **kwargs):
# Controleer gebruikersinformatie uit het request-object
if not request.user.is_authenticated:
return HttpResponseForbidden("Je moet ingelogd zijn om deze pagina te openen.")
# Roep de originele view-functie aan
return view_func(request, *args, **kwargs)
return _wrapped_view
5. Hoe parameters aan een decorator toe te voegen?
Als je wilt dat een decorator parameters accepteert, moet je een tweelaags functie-structuur gebruiken. Dit komt omdat de eerste functie wordt gebruikt om de parameters van de decorator te verwerken, terwijl de tweede functie de werkelijke view-functie omhult.
Basisstructuur:
def decorator_with_params(param1, param2):
def actual_decorator(view_func):
@wraps(view_func)
def _wrapped_view(request, *args, **kwargs):
# Logica met de parameters param1, param2
return view_func(request, *args, **kwargs)
return _wrapped_view
return actual_decorator
Uitleg:
- De eerste functie
decorator_with_params
verwerkt de parameters van de decorator (param1
,param2
). - Het retourneert de decoratorfunctie die de werkelijke view-functie omhult.
actual_decorator
roept de originele view-functie aan of voert extra logica uit.
6. Praktijkvoorbeeld: tijdgebonden toegang decorator
Hier is een voorbeeld van een decorator die alleen toegankelijk is op bepaalde tijdstippen. Deze decorator accepteert toegestane tijdsintervallen als parameters.
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("Deze pagina is alleen toegankelijk tijdens bepaalde uren.")
return view_func(request, *args, **kwargs)
return _wrapped_view
return decorator
@time_restricted_access(9, 17) # Toegestaan van 9:00 tot 17:00
def working_hours_view(request):
return render(request, 'working_hours.html')
Uitleg van de werking:
time_restricted_access
is de eerste functie die de parameters (start_hour
,end_hour
) verwerkt.- De eerste functie retourneert de decoratorfunctie die de view omhult.
- De decoratorfunctie ontvangt de
request
en controleert het huidige uur (datetime.now().hour
). Afhankelijk van de tijdvoorwaarden:- Als de voorwaarden zijn voldaan, wordt de view aangeroepen en wordt het resultaat geretourneerd.
- Als de voorwaarden niet zijn voldaan, wordt de toegang geblokkeerd met
HttpResponseForbidden
.
Waarom moeten we de functie twee keer omhullen?
De reden om de functie twee keer te omhullen is om de rollen van parameterverwerking en view-functie verwerking te scheiden.
- Eerste functie: accepteert parameters (
start_hour
,end_hour
) en genereert intern een decorator. - Tweede functie: de gegenereerde decorator omhult de view-functie en handelt het request af.
Deze structuur maakt decorators flexibel en herbruikbaar.
7. Gebruik in class-gebaseerde views (CBV)
Voor class-gebaseerde views moet je method_decorator
gebruiken.
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. Conclusie: Aandachtspunten bij het schrijven van een aangepaste decorator
- Houd het eenvoudig: de logica van de decorator moet eenvoudig en duidelijk zijn.
- Denk aan herbruikbaarheid: als bepaalde logica in meerdere views wordt gebruikt, extraheren als een decorator.
- Parameterverwerking: gebruik de tweelaags functie-structuur als er parameters nodig zijn.
- Metadata behouden: gebruik
@wraps
om de metadata van de originele functie te behouden.
Tot slot
Nu begrijp je de interne werking van aangepaste decorators in Django en kun je decorators maken die met parameters werken. Gebruik dit artikel als basis om decorators te schrijven die passen bij jouw project!
댓글이 없습니다.