Search code examples
pythonflaskdecoratorpython-decorators

Decorators with arguments with Flask


I'm trying to create a decorator with arguments and use it in conjunction with the flask module.

def ios_network_access(arg): #TODO: 
    def real_ios_network_access_decorator(fn):
        def ios_network_access_inner():
            if not request.json:
                print("aborting because not json", fn.__name__)
                abort(400)
            try: 
                print("check args", arg)
                return fn()
            except Exception as e:
                print("the following error occurred in:", fn.__name__)
                print(request.json)
                print(str(e))
                print("---------------------------------")
                abort(503)
   return real_ios_network_access_decorator
@app.route("/someurl")
@ios_network_access("some argument")
def some_function_for_url():
    pass

However, because flask uses function names in their decorator (flask requires uniqueness of function names and the decorator masks it), my end-points are not being created.

There is a very similar question here that asks regarding non-parameterized decorators; however, due to the additional function layer, this question is different. See AssertionError: View function mapping is overwriting an existing endpoint function: main

Any thoughts on how to pass an argument into a decorator given flask's qwerks?


Solution

  • wraps function is a convenience way to wrap your decorator function. Attributes of the wrapper function are updated with the corresponding attributes from the original function.

    from functools import wraps
    
    def ios_network_access(arg):
        def real_ios_network_access_decorator(fn):
            @wraps(fn)
            def ios_network_access_inner(*args, **kwds):
                if not request.json:
                    print("aborting because not json", fn.__name__)
                    abort(400)
                try: 
                    print("check args", arg)
                    return fn(*args, **kwds)
                except Exception as e:
                    print("the following error occurred in:", fn.__name__)
                    print(request.json)
                    print(str(e))
                    print("---------------------------------")
                    abort(503)
            return ios_network_access_inner
        return real_ios_network_access_decorator