10

このブログ投稿に投稿されたミックスインのコードを理解しようとしています。

これらのミックスインは、ミックスイン内login_requiredからデコレータを呼び出しますが、 fromによって装飾されます。以下のサンプルコードでは、デコレータを装飾する必要がある理由がわかりません。django.contrib.auth.decoratorsmethod_decoratordjango.utils.decoratorslogin_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) 
4

1 に答える 1

17

selfDjangoのmethod_decoratorは、装飾された関数に引数を正しく渡すように設定されています。run_eight_times上記でデコレータを使用して記述したテストケースにこれが表示されない理由は、 inner_funcinがすべての引数をandを介してmyfuncに盲目的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

    # 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-最初の署名を2番目の署名に変換します。

于 2012-03-05T06:15:35.367 に答える