I am trying to understand the code for the mixins posted at this blog post.
These mixins call the login_required decorator from django.contrib.auth.decorators within the mixins , but they do so decorated by the method_decorator from django.utils.decorators.
In the sample code below I dont understand why I need to decorate the login_required decorator .
from django.utils.decorators import method_decorator
from django.contrib.auth.decorators import login_required
class LoginRequiredMixin(object):
"""
View mixin which verifies that the user has authenticated.
NOTE:
This should be the left-most mixin of a view.
"""
# Why do I need to decorate login_required here
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(LoginRequiredMixin, self).dispatch(*args, **kwargs)
The method_decorator decorator says it is used to “Converts a function decorator into a method decorator” But in test code I can use my decorator even without the method_decorator.
My decorator
def run_eight_times(myfunc):
def inner_func(*args, **kwargs):
for i in range(8):
myfunc(*args, **kwargs)
return inner_func
My class which calls the above decorator directly produces the same result as if I called the decorator decorated by method_decorator
from django.utils.decorators import method_decorator
class Myclass(object):
def __init__(self,name,favorite_dish):
self.name = name
self.favorite_dish = favorite_dish
# This next line is not required
#@method_decorator(run_eight_times)
@run_eight_times
def undecorated_function(self):
print "%s likes spam in his favorite dish %s" % (self.name,self.favorite_dish)
Django’s method_decorator is set up to pass the
selfargument in correctly to the decorated function. The reason this doesn’t show up in the test cases you wrote above with therun_eight_timesdecorator is that theinner_funcinrun_eight_timesblindly passes all arguments in to myfunc via*argsand**kwargs. In general, this won’t be the case.To see this with your example, try the following:
Specifically, Django’s view decorators will return a function with a signature
(request, *args, **kwargs). For a class based-view, this should be(self, request, *args, **kwargs). That’s whatmethod_decoratordoes – transform the first signature into the second.