为什么需要使用@method_decorator来装饰login_required装饰器 [英] Why do I need to decorate login_required decorator with @method_decorator

查看:2085
本文介绍了为什么需要使用@method_decorator来装饰login_required装饰器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试了解此博文上发布的mixin的代码。



这些mixin从 django.contrib.auth.decorators c#c​​中添加 login_required code>,但它们由 method_decorator django.utils.decorators 进行装饰。
在下面的示例代码中,我不明白为什么我需要装饰 login_required 装饰器。



<$ p $ django.utils.decorators导入方法__decorator
从django.contrib.auth.decorators导入login_required
类LoginRequiredMixin(对象):
$ b $

注意:
这应该是视图最左边的混合

#为什么我需要在这里装饰login_required
@method_decorator(login_required)
def dispatch(self,* args,** kwargs):
return super(LoginRequiredMixin,self).dispatch(* args, ** kwargs)

method_decorator decorator说它用于将功能装饰器转换为方法装饰器但是在测试代码中,我可以使用我的装饰器,即使没有method_decorator。



我的装饰器

  def run_eight_time s(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

#下一行不需要
#@ method_decorator(run_eight_times)
@run_eight_times
def undecorated_function(self):
打印%s喜欢垃圾邮件在他最喜欢的菜%s %(self.name,self.favorite_dish)


解决方案

Django's method_decorator设置为将 self 参数正确传递给decorat ed功能。在上面用 run_eight_times 装饰器编写的测试用例中没有显示的原因是, inner_func run_eight_times 通过 * args ** 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

#下一行需要!
@method_decorator(run_eight_times)
#@ run_eight_times
def undecorated_function(self,what_he_likes):
print%s喜欢%s在他最喜欢的菜%s%(
self.name,what_he_likes,self.favorite_dish


def main():
inst = MyClass('bob','burrito')
inst $ d
$ b如果__name__ =='__main__':
main()

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


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 self argument in correctly to the decorated function. The reason this doesn't show up in the test cases you wrote above with the run_eight_times decorator is that the inner_func in run_eight_times blindly passes all arguments in to myfunc via *args and **kwargs. In general, this won't be the case.

To see this with your example, try the following:

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

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 what method_decorator does - transform the first signature into the second.

这篇关于为什么需要使用@method_decorator来装饰login_required装饰器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆