vvpoloskin
@vvpoloskin
Инженер связи

Как реализовать декоратор класса в python?

Вопрос знатокам python.
Исходная задача - необходимо, чтобы один из методов класса оборачивался в декораторы. Это можно сделать через переопределение этого метода и оборачиванием его через method_decorator.

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

Я не хочу переписывать каждый раз этот метод. Мне кажется более логичным такое решение
@viewdecorator(login_required)
class MyView(View):
    pass

Вот вопрос - как написать viewdecorator?

Сейчас я написал следующее:
def viewdecorator(decorator):
    def wrap(cls):
        dispatch = getattr(cls, 'dispatch', None)
        if dispatch:
            setattr(cls, 'dispatch', method_decorator(decorator))
        return cls
    return wrap

При этом почему-то не переносятся classmethod-ы и classonlymethod-ы. Конкретно в моем случае не идет as_view().
Как сделать так, чтоб это перенеслось?
  • Вопрос задан
  • 14096 просмотров
Решения вопроса 1
vvpoloskin
@vvpoloskin Автор вопроса
Инженер связи
В общем разобрался и получилось. Если кому-то будет интересно ниже чистый код без всяких наследований и пример его применения.
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'
Ответ написан
Пригласить эксперта
Ответы на вопрос 4
abukin
@abukin
Программирую на Python
class LoginRequiredMixin(View):

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


И от этого класса наследуете все свои порожденные вьюхи.
Например:

class ProfileUpdateView(LoginRequiredMixin, UpdateView):
...


Только следите за тем чтобы LoginRequiredMixin был первым базовым классом. Т.к первым делом будет вызываться его dispatch а потом уже все остальные, если пройдут проверку.
Ответ написан
MAKAPOH
@MAKAPOH
многостаночник
Если всё правильно понял, то вам поможет эта статья.
Ответ написан
Rrooom
@Rrooom
Может не будете костылить? А используете наследование?
Еще в urls.py можно обернуть вьюху login_requireдом. Тоже частая метода.
Ответ написан
@Joyniter
Всегда что-то начинающий и изучающий
Как мне декорировать функцию (метод) внутри класса?
class Example:
    def func(self, f):
        # что-то делает
        f()
        return 'decorate'
     @func
     def f1(self)
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы