我正在尝试了解在this blog post发布的mixins的代码。
这些mixins在mixins中调用来自login_required
的{{1}}装饰器,但它们由来自django.contrib.auth.decorators
的{{1}}装饰。
在下面的示例代码中,我不明白为什么我需要装饰method_decorator
装饰器。
django.utils.decorators
login_required
装饰器说它用于“将函数装饰器转换为方法装饰器”但是在测试代码中,即使没有method_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)
我的类直接调用上面的装饰器会产生与调用method_decorator
def run_eight_times(myfunc):
def inner_func(*args, **kwargs):
for i in range(8):
myfunc(*args, **kwargs)
return inner_func
答案 0 :(得分:16)
Django的method_decorator设置为正确地将self
参数传递给修饰函数。您在上面使用run_eight_times
装饰器编写的测试用例中没有显示的原因是inner_func
中的run_eight_times
通过*args
盲目地将所有参数传递给myfunc和**kwargs
。一般来说,情况并非如此。
要通过示例查看此内容,请尝试以下操作:
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
所做的 - 将第一个签名转换为第二个签名。