#29253 closed Bug (fixed)
method_decorator() with list argument doesn't copy over attributes of the decorator function
| Reported by: | Chris Jerdonek | Owned by: | Chris Jerdonek |
|---|---|---|---|
| Component: | Utilities | Version: | 2.0 |
| Severity: | Normal | Keywords: | decorators |
| Cc: | Triage Stage: | Accepted | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
The docs say that the "list" form of @method_decorator is equivalent to invoking it multiple times:
decorators = [never_cache, login_required] @method_decorator(decorators, name='dispatch') class ProtectedView(TemplateView): template_name = 'secret.html' @method_decorator(never_cache, name='dispatch') @method_decorator(login_required, name='dispatch') class ProtectedView(TemplateView): template_name = 'secret.html'
However, it appears there is a slight difference in behavior. For example:
from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt def my_decorator(func): def new_func(*args, **kwargs): func(*args, **kwargs) return new_func @method_decorator(my_decorator, name='dispatch') @method_decorator(csrf_exempt, name='dispatch') class View1: def dispatch(self): pass @method_decorator([my_decorator, csrf_exempt], name='dispatch') class View2: def dispatch(self): pass print(hasattr(View1.dispatch, 'csrf_exempt')) print(hasattr(View2.dispatch, 'csrf_exempt'))
results in the output--
True False
It appears this is because method_decorator() takes a short cut when processing a list. It doesn't carry over the attributes of the decorated function like it does in the normal case.
Change History (8)
comment:1 by , 8 years ago
comment:2 by , 8 years ago
| Summary: | method_decorator behaves differently with list argument → method_decorator() with list argument doesn't copy over attributes of the decorator function |
|---|---|
| Triage Stage: | Unreviewed → Accepted |
comment:3 by , 8 years ago
| Owner: | changed from to |
|---|---|
| Status: | new → assigned |
comment:4 by , 8 years ago
| Has patch: | set |
|---|
I prepared a pull request here: https://github.com/django/django/pull/9819
comment:6 by , 7 years ago
PR 10091 fixes a regression where @method_decorator(transaction.non_atomic_requests) crashes.
The behavior difference described in this ticket is actually noted in the discussion of the patch here, but it was thought not important. I do think it's important though because, for example, it can cause decorators to have or not have an effect depending on which invocation style is used.