Search code examples
pythonflaskdecoratorpython-decorators

Decorator passing arguments as KWARGS but need positional args in flask API end point


I have a flask application with many endpoints and I planning to write a decorator which will log the actions of APIs end points.

For example, I have a end point to delete an entry as below for API call http://localhost:5000/api/owners/123/delete

@route('/owners/<ownerid>/delete',methods=['DELETE'])
def deleteOwner(ownerid):
     if request.method == 'DELETE':
         """ delete action """
         return jsonify({})

Now I want to add a decorator to this call so it logs the user actions. So I am trying out with a decorator as below

def logtrail(func):
    def wrap(*args, **kwargs):
        print args
        print kwargs.values()  #This prints {"ownerid":"123"}
        return func(kwargs)
    return wrap

Now decorating as below

@route('/owners/<ownerid>/delete',methods=['DELETE'])
@logtrail
def deleteOwner(ownerid):
     if request.method == 'DELETE':
         """ delete action """
         return jsonify({})

When I decorate my original API method with @logtrail, the "ownerid" which I need as a positional argument is passed as {"ownerid":"123"} to the decorator function.

I am new to decorators and need some help on how to approach this.


Solution

  • The issue is related on how variables works / arguments are passed on python. To fix it, just change return func(kwargs) to return func(**kwargs), so the kwargs will be passed as keywords instead of a dict.

    def logtrail(func):
        def wrap(*args, **kwargs):
            print args
            print kwargs.values()  #This prints {"ownerid":"123"}
            return func(**kwargs)
        return wrap