Декораторы Python и наследование классов

Я пытаюсь использовать декораторов для управления способом, которым пользователи могут или не могут получить доступ к ресурсам в рамках веб-приложения (работающий на Google App Engine). Обратите внимание на то, что я не позволяю пользователям входить в систему с их учетными записями Google, таким образом устанавливание определенных прав доступа к определенным маршрутам в app.yaml не является опцией.

Я использовал следующие ресурсы:
- Руководство Bruce Eckel по декораторам
- ТАК: get-class-in-python-decorator2
- ТАК: python-decorators-and-inheritance
- ТАК: get-class-in-python-decorator

Однако я все еще немного смущен...

Вот мой код! В следующем примере current_user является @property методом, которые принадлежат классу RequestHandler. Это возвращает Пользователя (db.model) объект, хранивший в хранилище данных с уровнем IntProperty ().

class FoobarController(RequestHandler):

    # Access decorator
    def requiredLevel(required_level):
        def wrap(func):
            def f(self, *args):
                if self.current_user.level >= required_level:
                    func(self, *args)
                else:
                    raise Exception('Insufficient level to access this resource') 
            return f
        return wrap

    @requiredLevel(100)
    def get(self, someparameters):
        #do stuff here...

    @requiredLevel(200)
    def post(self):
        #do something else here...

Однако мое приложение использует различные контроллеры для другого вида ресурсов. Для использования @requiredLevel декоратора во всех подклассах я должен переместить его в родительский класс (RequestHandler):

class RequestHandler(webapp.RequestHandler):

    #Access decorator
    def requiredLevel(required_level):
        #See code above

Моя идея состоит в том, чтобы получить доступ к декоратору во всех подклассах контроллера с помощью следующего кода:

class FoobarController(RequestHandler):

    @RequestHandler.requiredLevel(100)
    def get(self):
        #do stuff here...

Я думаю, что просто достиг предела своего знания о декораторах и наследовании классов :). Какие-либо мысли?

9
задан Community 23 May 2017 в 00:29
поделиться

1 ответ

Покопавшись в StackOverflow и внимательно прочитав руководство Брюса Экеля по декораторам , я думаю, что нашел возможное решение.

Это включает реализацию декоратора как класса в родительском классе:

class RequestHandler(webapp.RequestHandler):

    # Decorator class :
    class requiredLevel(object):
        def __init__(self, required_level):
            self.required_level = required_level

        def __call__(self, f):
            def wrapped_f(*f_args):
                if f_args[0].current_user.level >= self.required_level:
                    return f(*f_args)
                else:
                    raise Exception('User has insufficient level to access this resource') 
            return wrapped_f

Это делает работу! Использование f_args [0] кажется мне немного грязным, я отредактирую этот ответ, если найду что-то более красивое.

Затем вы можете декорировать методы в подклассах следующим образом:

FooController(RequestHandler):
    @RequestHandler.requiredLevel(100)
    def get(self, id):
        # Do something here

    @RequestHandler.requiredLevel(250)
    def post(self)
        # Do some stuff here

BarController(RequestHandler):
    @RequestHandler.requiredLevel(500)
    def get(self, id):
        # Do something here

Не стесняйтесь комментировать или предлагать улучшения.

1
ответ дан 3 November 2019 в 07:11
поделиться
Другие вопросы по тегам:

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