Welcome back to this series of tutorial on Flask and complex apps.

The decorator pattern

The decorator pattern is one of those patterns that nowadays we encounter in a variety of frameworks.

From The Gang of Four’s book:

Decorators Attach additional responsibilities to an object dynamically.
Decorators provide a flexible alternative to subclassing for extending functionality.
Also Known As Wrapper

When it comes to a function we have two possibilities:

1) We don’t pass any extra parameters from the caller because we do not need to do some extra computation

def example_decorator_function(original_function):      
    def some_new_function(*args,**kwargs):
        print("Back to the future")              
        x = original_function(*args,**kwargs)                
        print("American Pie"); 
        return x                                             
    return some_new_function()                                   
    
@example_decorator_function
def func_a(stuff):
    print("Life is beautiful and " + stuff)
func_a("amazing")

2) We pass some extra parameters for example for some verification purposes

def router_acl(user_type):
    def router_acl_decorator(fn):
        @wraps(fn)  # it basically updates the context with the new function, variables, etc.
        def func_wrapper(*args, **kwargs):
            current_user = CurrentUserHelper()
            if request.method == 'GET':
                if user_type == CURRENT_USER_ONLY:
                    if current_user.id == int(request.args.get('user_id')):
                        return fn()
                    else:
                        # you can test this by changing status to whatever you like and
                        # then trying to connect to a route with
                        # a wrong user id e.g. http://localhost:5001/api/user/edit?id=24
                        response = json.jsonify({"status": "fail"})
                        response.status_code = 403
                        return response

wraps() is a decorator, a shortcut for update_wrapper() that lies in functools.py from Python’s core library. Without this, on repetead calls of the function the context remains the one of the first call.

You can find the complete code here

Related Post