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

Hsn*_*edi 5 django inheritance decorator django-class-based-views csrf-token

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

@method_decorator(ensure_csrf_cookie, name='dispatch')
class SomeView(ListView):
    ...     
Run Code Online (Sandbox Code Playgroud)

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

bru*_*ers 4

“@decorator”语法只是转换此内容的语法糖:

@decorator
class SomeClass(parent):
    pass
Run Code Online (Sandbox Code Playgroud)

进入这个:

class SomeClass(parent):
    pass

SomeClass = decorator(SomeClass)
Run Code Online (Sandbox Code Playgroud)

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
>>> 
Run Code Online (Sandbox Code Playgroud)