2012-03-05 102 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所做的 - 將第一個簽名轉換爲第二個簽名。

相關問題