Using decorators, there are quite some ways to achieve the desired behavior.
1. If you only want to mark a class for the middleware to do something
from django.utils.decorators import classonlymethod
def special_marker(class_view):
def as_view(cls, **initkwargs):
view = super(cls, cls).as_view(**initkwargs)
view.special_marker = True
return view
return type(class_view.__name__, (class_view,), {
'as_view': classonlymethod(as_view),
})
@special_marker
class MyView(View):
pass
class MyMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
return self.get_response(request)
def process_view(self, request, view_func, view_args, view_kwargs):
special_marker = getattr(view_func, 'special_marker', False)
if special_marker:
# Do something
2. If you want to pass some data to the middleware that you don't need in the view
from django.utils.decorators import classonlymethod
def tell_middleware(**kwargs):
def wrapper(class_view):
def as_view(cls, **initkwargs):
view = super(cls, cls).as_view(**initkwargs)
for k, v in kwargs.items():
setattr(view, k, v)
return view
return type(class_view.__name__, (class_view,), {
'as_view': classonlymethod(as_view),
})
return wrapper
@tell_middleware(my_attribute='something')
class MyView(View):
pass
class MyMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
return self.get_response(request)
def process_view(self, request, view_func, view_args, view_kwargs):
my_attribute = getattr(view_func, 'my_attribute', 'default value')
if my_attribute == 'something':
# Do something
3. If you want to expose some view attributes to the middleware
from django.utils.decorators import classonlymethod
def expose_to_middleware(*args):
def wrapper(class_view):
def as_view(cls, **initkwargs):
view = super(cls, cls).as_view(**initkwargs)
for attr in args:
setattr(view, attr, getattr(class_view, attr)
return view
return type(class_view.__name__, (class_view,), {
'as_view': classonlymethod(as_view),
})
return wrapper
@expose_to_middleware('my_attribute', 'my_other_attribute')
class MyView(View):
my_attribute = 'something'
my_other_attribute = 'else'
unexposed_attribute = 'foobar'
class MyMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
return self.get_response(request)
def process_view(self, request, view_func, view_args, view_kwargs):
my_attribute = getattr(view_func, 'my_attribute', 'default value')
if my_attribute == 'something':
# Do something
4. If you want to expose the whole class based view to the middleware
from django.utils.decorators import classonlymethod
def expose_cbv_to_middleware(class_view):
def as_view(cls, **initkwargs):
view = super(cls, cls).as_view(**initkwargs)
view.cbv = class_view
return view
return type(class_view.__name__, (class_view,), {
'as_view': classonlymethod(as_view),
})
@expose_cbv_to_middleware
class MyView(View):
my_attribute = 'something'
class MyMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
return self.get_response(request)
def process_view(self, request, view_func, view_args, view_kwargs):
cbv = getattr(view_func, 'cbv', None)
if cbv:
if hasattr(cbv, 'my_attribute'):
print(cbv.my_attribute)
get_context_data()
. This gets the job done, but this functionality is required for every request, so I'd like to avoid having to inherit from the mixin in every single view in the application. – Ossuary