9

Próbuję zrozumieć kod dla mixins zamieszczone na this blog post.Dlaczego muszę ozdobić dekoratora login_required za pomocą @method_decorator

Te wstawek wywołać login_required dekorator z django.contrib.auth.decorators obrębie wstawek, ale robią tak urządzone przez method_decorator od django.utils.decorators. W przykładowym kodzie poniżej nie rozumiem, dlaczego muszę ozdobić dekorator login_required.

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) 

method_decorator dekorator mówi służy do „Zamienia dekorator funkcji w metodzie dekorator” Ale w kodzie testowym mogę używać mojego dekorator nawet bez method_decorator.

Moja dekorator

def run_eight_times(myfunc): 
    def inner_func(*args, **kwargs): 
     for i in range(8): 
      myfunc(*args, **kwargs) 
    return inner_func 

Moja klasa, która nazywa powyżej dekorator bezpośrednio wywołuje taki sam efekt, jak gdybym nazwał dekorator urządzone przez 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) 

Odpowiedz

15

method_decorator Django jest skonfigurowany do zabicia self argument poprawnie do udekorowanej funkcji. Powodem, dla którego to nie pojawia się w przypadkach testowych, które napisałeś wyżej z dekoratorem run_eight_times jest to, że inner_func w run_eight_times ślepo przekazuje wszystkie argumenty do myfunc przez *args i **kwargs. Zasadniczo tak nie będzie.

to zobaczyć na swoim przykładzie, spróbuj wykonać następujące czynności:

from django.utils.decorators import method_decorator 

def run_eight_times(myfunc): 
    def inner_func(what_he_likes, **kwargs): 
     # override... 
     what_he_likes = 'pizza' 
     for i in range(8): 
      myfunc(what_he_likes, **kwargs) 
    return inner_func 

class MyClass(object): 

    def __init__(self, name, favorite_dish): 
     self.name = name 
     self.favorite_dish = favorite_dish 

    # This next line required! 
    @method_decorator(run_eight_times) 
    #@run_eight_times 
    def undecorated_function(self, what_he_likes): 
     print "%s likes %s in his favorite dish %s" % (
      self.name, what_he_likes, self.favorite_dish 
     ) 

def main(): 
    inst = MyClass('bob', 'burrito') 
    inst.undecorated_function('hammy spam') 

if __name__ == '__main__': 
    main() 

szczególności Django zobacz dekoratorzy powróci do funkcji z podpisem (request, *args, **kwargs). W przypadku widoku opartego na klasie powinno to być (self, request, *args, **kwargs). To właśnie robi method_decorator - przekształca pierwszą sygnaturę na drugą.

Powiązane problemy