2012-03-05 108 views
9

我想了解发布在this blog post上的mixins的代码。为什么我需要用@method_decorator装饰login_required装饰器

这些混入从混入内django.contrib.auth.decorators致电login_required装饰,但他们这样做由method_decoratordjango.utils.decorators装饰。 在下面的示例代码中,我不明白为什么我需要装饰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装饰说它是用来“功能装饰转换为一个方法装饰”但在测试代码,我可以用我的装饰,即使没有method_decorator。

我的装饰

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

我的类调用上面的装饰直接产生相同的结果,如果我叫装饰用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) 

回答

15

Django的method_decorator设置为通过self参数正确的装饰功能。这并不在你上面​​的run_eight_times装饰写测试用例出现的原因是,在run_eight_timesinner_func通过*args**kwargs盲目地传递到MYFUNC所有参数。一般情况下,情况并非如此。

要查看这跟你的榜样,请尝试以下操作:

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() 

具体来说,Django的观点装饰将返回一个函数的签名(request, *args, **kwargs)。对于基于类的视图,这应该是(self, request, *args, **kwargs)。这就是method_decorator所做的 - 将第一个签名转换为第二个签名。

相关问题