Я понимаю, что эта тема немного устарела, но все равно вот мои два цента.
со следующим кодом:
from django.utils.decorators import method_decorator
from inspect import isfunction
class _cbv_decorate(object):
def __init__(self, dec):
self.dec = method_decorator(dec)
def __call__(self, obj):
obj.dispatch = self.dec(obj.dispatch)
return obj
def patch_view_decorator(dec):
def _conditional(view):
if isfunction(view):
return dec(view)
return _cbv_decorate(dec)(view)
return _conditional
у нас теперь есть возможность исправления декоратора, чтобы он стал многофункциональным. Это фактически означает, что при применении к обычному представителю декорации, например, так:
login_required = patch_view_decorator(login_required)
этот декоратор по-прежнему будет работать, если использовать его так, как он был изначально предназначен:
@login_required
def foo(request):
return HttpResponse('bar')
, но при правильном использовании также будет работать так:
@login_required
class FooView(DetailView):
model = Foo
Похоже, что это хорошо работает в нескольких случаях, с которыми я недавно сталкивался, включая пример из реальной жизни:
@patch_view_decorator
def ajax_view(view):
def _inner(request, *args, **kwargs):
if request.is_ajax():
return view(request, *args, **kwargs)
else:
raise Http404
return _inner
Функция ajax_view написана для изменения представления (на основе функции), так что оно вызывает ошибку 404 всякий раз, когда это представление посещается не-ajax-вызовом. Просто применяя функцию patch в качестве декоратора, этот декоратор также может работать в представлениях на основе классов