If I have a function that looks like:
@app.route('/categories/id/<int:id>/edit')
@login_required
def edit_category(id):
#some code...
And the login_required decorator looks like this
def login_required(f):
@wraps(f)
def wrapper(*args, **kwargs):
print id #given to edit_category by app.route decorator
return f(*args, **kwargs)
return wrapper
How do I access the id variable that is given to edit_category as an argument by the app.route decorator, from the login_required decorator?
The trick is to inspect the name of the second argument. Then, in the decorator, you check to see if that name is present in kwargs . If yes, then you use that. If no, then you use args .
To fix this, you need to change the repeat decorator so that it accepts an argument that specifies the number of times a function should execute like this: @repeat(5) def say(message): ... To define the repeat decorator, the repeat(5) should return the original decorator. The new repeat function returns a decorator.
Because functions are objects we can pass them as arguments to other functions. Functions that can accept other functions as arguments are also called higher-order functions.
The decorator arguments are accessible to the inner decorator through a closure, exactly like how the wrapped() inner function can access f . And since closures extend to all the levels of inner functions, arg is also accessible from within wrapped() if necessary.
The positional arguments to the wrapper function come in the args
(first argument - *args
) , and the keyword arguments for the method come in kwargs
(second argument - **kwargs
).
args
is a tuple , where the first element refers to the first positional argument, second element is the second positional argument.
kwargs
is a dictionary , where the key is the keyword (for the argument) and the value is the value passed in for that keyword.
Example -
>>> def decor(func):
... def wrapper(*args, **kwargs):
... print('args - ',args)
... print('kwargs - ',kwargs)
... return func(*args, **kwargs)
... return wrapper
...
>>> @decor
... def a(*a, **b):
... print("In a")
... print(a)
... print(b)
...
>>> a(1,2,x=10,y=20)
args - (1, 2)
kwargs - {'y': 20, 'x': 10}
In a
(1, 2)
{'y': 20, 'x': 10}
You can test whether app.route
is sending id
as positional argument or keyword argument by printing both args
and kwargs
and take the correct value. I think it may be coming in as positional argument, if so, it would be the first element of args
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With