django基于类的视图会继承method_decorators吗?

时间:2019-03-08 09:52:27

标签: django inheritance decorator django-class-based-views csrf-token

我正在使用基于django类的视图。假设有一个这样的ListView:

@method_decorator(ensure_csrf_cookie, name='dispatch')
class SomeView(ListView):
    ...     

如果另一个基于类的视图继承了SomeView,它是否也继承了“ ensure_csrf_cookie”?还是必须在每个子类上都明确定义它?

2 个答案:

答案 0 :(得分:1)

“ @ decorator”语法只是语法糖,可以改变这种情况:

@decorator
class SomeClass(parent):
    pass

对此:

class SomeClass(parent):
    pass

SomeClass = decorator(SomeClass)

IOW,decorator的任何操作都是在创建类后 完成的,因此,作为一般规则,您不能指望它由SomeClass的子类继承- “装饰者所做的事情”是否会真正继承(或不继承),实际上取决于“装饰者所做的事情”和子类定义。

wrt /您的具体用例:method_decorator用于修饰类的给定方法(示例中的dispatch方法)。如果您的子类没有重写此方法,则将在父类上查找它。在这种情况下,您实际上将最终使用装饰方法。但是,如果您在子类中覆盖了修饰的方法,则将使用新方法代替父方法的新方法,因此不会自动修饰它,您将不得不再次应用修饰器。

FWIW,您自己进行测试非常容易:

>>> def decorator(func):
...     def wrapper(*args, **kw):
...         print("before %s(%s, %s)" % (func, args, kw)
... )
...         return func(*args, **kw)
...     return wrapper
... 
>>> from django.utils.decorators import method_decorator
>>> @method_decorator(decorator, name='foo')
... class Bar(object):
...     def foo(self):
...         print("%s.foo()"  % self)
... 
>>> b = Bar()
>>> b.foo()
before <function bound_func at 0x7fefab044050>((), {})
<Bar object at 0x7fefab09af10>.foo()
>>> class Quux(Bar): pass
... 
>>> q = Quux()
>>> q.foo()
before <function bound_func at 0x7fefab044050>((), {})
<Quux object at 0x7fefab041110>.foo()
>>> class Baaz(Bar):
...     def foo(self):
...         print("this is Baaz.foo")
... 
>>> bz = Baaz()
>>> bz.foo()
this is Baaz.foo
>>> 

答案 1 :(得分:0)

必须在每个子类上明确定义它。因为method_decorator只是函数并且要进行一些计算(取决于您编写装饰器的方式),所以它将调用您的类SomeView。如果继承SomeView,则必须为该新类显式使用method_decorator。可能有帮助。