Django基于类的视图是否继承method_decorators?

5

我将使用Django基于类的视图。假设有一个如下所示的ListView:

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

如果另一个基于类的视图继承了SomeView,那么它是否也会继承“ensure_csrf_cookie”呢?还是必须在每个子类中显式定义?
2个回答

4
"@decorator"语法只是一种简单的语法糖,可将以下代码转换为:
@decorator
class SomeClass(parent):
    pass

转换成这样:

class SomeClass(parent):
    pass

SomeClass = decorator(SomeClass)

换言之,decorator所做的任何操作都是在类创建后完成的,因此一般而言,您不能指望它被SomeClass的子类继承 - 是否实际继承“装饰器所做的操作”取决于“装饰器所做的操作”和子类定义。

就您的具体用例而言:method_decorator用于装饰类中的特定方法(在您的示例中是dispatch方法)。如果您的子类没有覆盖此方法,则会在父类上查找该方法。在这种情况下,您确实将使用装饰方法。但是,如果您在子类中覆盖了装饰方法,则新方法将代替父类的方法,因此它将不会自动装饰,您必须再次应用装饰器。

顺便说一句,您可以很容易地自行测试:

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

0

必须在每个子类中明确定义。因为method_decorator只是一个函数并且执行一些计算(它取决于你如何编写你的装饰器),然后它将调用你的SomeView类。如果你继承了SomeView,那么你必须明确地为这个新类使用method_decorator。这可能会有所帮助。


@HsnVahedi 哎呀,这个答案不太精确 - 它取决于装饰器的作用以及您如何定义子类之间的一些交互。 - bruno desthuilliers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接