V
V
Valentine2014-10-10 15:57:51
Django
Valentine, 2014-10-10 15:57:51

How to implement a class decorator in python?

Question for python experts.
The initial task is to wrap one of the class methods in decorators. This can be done by overriding this method and wrapping it in a method_decorator.

class MyView(View):
   @method_decorator(login_required):
   def dispatch(self, *args, **kwargs):
       return super(MyView, self).dispatch(*args, **kwargs)

I don't want to rewrite this method every time. I think this is more logical
@viewdecorator(login_required)
class MyView(View):
    pass

Here's the question - how to write a viewdecorator ?
Now I have written the following:
def viewdecorator(decorator):
    def wrap(cls):
        dispatch = getattr(cls, 'dispatch', None)
        if dispatch:
            setattr(cls, 'dispatch', method_decorator(decorator))
        return cls
    return wrap

At the same time, for some reason, classmethods and classonlymethods are not transferred. Specifically, in my case, as_view () does not go.
How to make it transfer?

Answer the question

In order to leave comments, you need to log in

5 answer(s)
V
Valentin, 2014-10-13
@vvpoloskin

In general, I figured it out and it turned out. If someone is interested, below is a clean code without any inheritance and an example of its use.

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'

A
Alexey Bukin, 2014-10-11
@abukin

class LoginRequiredMixin(View):

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super(LoginRequiredMixin, self).dispatch(*args, **kwargs)

And from this class you inherit all your generated views.
For example:
class ProfileUpdateView(LoginRequiredMixin, UpdateView):
...

Just make sure LoginRequiredMixin is the first base class. Because its dispatch will be called first, and then all the others, if they pass the test.

A
Alexey, 2014-10-10
@MAKAPOH

If you understand everything correctly, then this article will help you.

R
Rrooom, 2014-10-10
@Rrooom

Maybe you will not crutch? Are you using inheritance?
You can also wrap the login_require view in urls.py. Also a common method.

V
Vita Aduchiev, 2020-01-10
@Joyniter

How do I decorate a function (method) inside a class?

class Example:
    def func(self, f):
        # что-то делает
        f()
        return 'decorate'
     @func
     def f1(self)

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question