0

I want to wrap one of the methods of class in decorator. If this necessary, my class is django class based view.

First type of implementation is wrap method by method_decorator:

class MyView(View): template_name = "index.html" @method_decorator(login_required): def dispatch(self, *args, **kwargs): return super(MyView, self).dispatch(*args, **kwargs) 

Ok, this works. But I don't want to every time overwrite method dispatch.

Second way - mixins and multiple inheritance.

class LoginRequiredView(object): @method_decorator(login_required): def dispatch(self, *args, **kwargs): return super(MyView, self).dispatch(*args, **kwargs) class MyView(LoginRequiredView, View): template_name = "index.html" 

This works too. But if I want to use multiple decorators, it is required to list all mixins in parents. It is not very good for me.

I want next:

@viewdecorator(login_required) class MyView(LoginRequiredView, View): template_name = "index.html" 

And my question is how to implement viewdecorator. I try to write this:

def viewdecorator(decorator): def wrap(cls): dispatch = getattr(cls, 'dispatch', None) if dispatch: setattr(cls, 'dispatch', method_decorator(decorator)) return cls return wrap 

But resulting cls in this decorator don't contains original classmethods and classonlymethods. I guess about a reason such behavior.

How to write viewdecorator to classmethods will be presented in resulting cls?

UPD: I understood how this work and below actual working code with example

def viewdecorator(decorator): def wrap(cls): getattribute = cls.__getattribute__ def newgetattr(cls, name): attr = getattribute(cls, name) if name == 'dispatch': return decorator(method_decorator(attr)) return attr cls.__getattribute__ = newgetattr return cls return wrap @viewdecorator(login_required) @viewdecorator(csrf_exempt) class EntriesMyList(EntriesList): template_name = 'index.html' 
6
  • So what you're saying is if dispatch is a classmethod, then your viewdecorator won't work? classmethod must be the top-most decorators, but maybe there's a workaround. Commented Oct 13, 2014 at 6:38
  • viewdecorator looks good to me, I don't understand what you meant by "resulting cls in this decorator don't contains original classmethods and classonlymethods"? It definitely contains all the methods. Also you need to set 'dispatch' to method_decorator(decorator)(dispatch). Commented Oct 13, 2014 at 7:00
  • @simonzack No, you can place @classmethod anywhere. Commented Oct 13, 2014 at 7:06
  • @AshwiniChaudhary I'm not sure about that, see stackoverflow.com/questions/1987919/… Commented Oct 13, 2014 at 7:08
  • Ok, in viewdecorator cls does not contain methods as_view, dispatch. Why? Commented Oct 13, 2014 at 7:09

1 Answer 1

0

You can install django-braces. This library contains login required mixin

from django.views.generic import View from braces.views import LoginRequiredMixin class SimpleView(LoginRequiredMixin, View): pass 

For correct style you don't need decorators for CBV. If you need some custom view permissions implement you logic in dispatch view method.

Sign up to request clarification or add additional context in comments.

1 Comment

As result I will get a long list of parents for view. Not very good. In the end of question I wrote useful solution.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.