I'm using django class-based views. Suppose there is a ListView like this:
@method_decorator(ensure_csrf_cookie, name='dispatch')
class SomeView(ListView):
...
If another class-based view inherits SomeView, Does it inherit the "ensure_csrf_cookie" too? Or it has to be defined on every subclasses explicitly?
The "@decorator" syntax is just syntactic sugar that transforms this:
@decorator
class SomeClass(parent):
pass
into this:
class SomeClass(parent):
pass
SomeClass = decorator(SomeClass)
IOW, whatever decorator
do is done after the class is created, so as a general rule, you cannot count on it being inherited by child classes of SomeClass
- whether "what the decorator did" will actually be inherited (or not) really depends on both "what the decorator did" AND the child class definition.
wrt/ your concrete use case: method_decorator
is used to decorate a given method of your class (the dispatch
method in your example). If your child class doesn't override this method, then it will be looked up on the parent class. In this case, you will indeed end up using the decorated method. But if you override the decorated method in your subclass, the new method will be used instead of the parent's one, so it will not be automagically decorated and you'll have to apply the decorator again.
FWIW, it's quite easy to test by yourself:
>>> 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
>>>