简体   繁体   中英

How to externalize the decorator in python flask application

I have written a python Flask application, which has a class and methods as below.

class PythonSample:
    def method1():
        pass # does something

    def method2():
        pass # does something

Now I have written another class which has decorator functions as below.

class PythonAuth:
    def oauthAuth():
        pass

Now I'm wiring oauthAuth decorator for all the methods of PythonSample class as below

import oauthAuth from PythonAuth

class PythonSample
    @oauthAuth
    def method1():
        pass # does something

    @oauthAuth
    def method2():
        pass # does something

Applying decorator at each method works fine.

Question: Instead of applying oauthAuth decorator to each of the methods. Is there a way to configure in python, as apply oauthAuth decorator to all the methods in a class and exclude certain methods.

Something like include auth for certain URLs and exclude authentication for certain urls

Please ignore the syntax of the python code here.

You can use a class decorator plus some magic.

Decorating Functions

Assume you have a decorator that just logs a string before calling the function.

def log(func):
    def logged_func(*args, **kwargs):
            print('logged')
            func(*args, **kwargs)
    return logged_func

Decorating classes

You can use the same trick, but with a class. log_all is a class decorator, cls is a class type. We use vars to walk the class dictionary, and look for methods by using callable(v) . Decorate the method with log(v) and use setattr to change the cls definition to the new decorated method. Just like function decorators, return the class in the end.

def log_all(cls):
    for k, v in vars(cls).items():
            if callable(v):
                    setattr(cls, k, log(v))
    return cls

I am ignoring k essentially, but k is the method name, you could leverage it to achieve your usage scenario.

Full code

Here is a full example, that should make some sense now.

def log(func):
    def logged_func(*args, **kwargs):
            print('logged')
            func(*args, **kwargs)
    return logged_func

def log_all(cls):
    for k, v in vars(cls).items():
            if callable(v):
                    setattr(cls, k, log(v))
    return cls

@log_all
class A:
    def method(self):
            pass

Every method in class A should be decorated with the log decorator.

>>> a = A()
>>> a.method()
logged

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM