Python Flask Decorator

I need to add a python decorator to the Flask route functions (basically I edited the code here )

def requires_admin(f): def wrapper(f): @wraps(f) def wrapped(*args, **kwargs): #if not admin: #return render_template('error.html') return f(*args, **kwargs) return wrapped return wrapper 

and use it, as it will be in order:

 @app.route('/admin/action') @requires_admin def AdminAction(): #NO error if NO parameter 

But use it as if it would have an error:

 @app.route('/admin/action/<int:id>') @requires_admin def AdminAction(id): 

In Flask 0.10, I get such errors (I just updated from Flask 0.9 to 0.10, and in Flask 0.9 there is no such grammatical error):

  @requires_admin File "/usr/local/lib/python2.6/dist-packages/Flask-0.10.1-py2.6.egg/flask/app. py", line 1013, in decorator self.add_url_rule(rule, endpoint, f, **options) File "/usr/local/lib/python2.6/dist-packages/Flask-0.10.1-py2.6.egg/flask/app. py", line 62, in wrapper_func return f(self, *args, **kwargs) File "/usr/local/lib/python2.6/dist-packages/Flask-0.10.1-py2.6.egg/flask/app. py", line 984, in add_url_rule 'existing endpoint function: %s' % endpoint) AssertionError: View function mapping is overwriting an existing endpoint functi on: wrapper 

I am new to decorator materials, how can I fix this error?

+7
python flask decorator
source share
2 answers

You have two wrapper functions where you only need one. Note that each wrapper function takes one argument. This should be the key to what is happening.

You have:

 def decorator(take_a_function): def wrapper1(take_a_function): def wrapper2(*takes_multiple_arguments): # do stuff return take_a_function(*takes_multiple_arguments) return wrapper2 return wrapper1 

When you decorate a function with it:

 @decorator def my_function(*takes_multiple_arguments): pass 

This is equivalent to:

 def my_function(*takes_multiple_arguments): pass my_function = decorator(my_function) 

but executing decorator(my_function) returns wrapper1 , which, if you recall, takes one argument, take_a_function . This is clearly not what you want. You want to return wrapper2 . As in your answer, the solution is to remove the outer shell ( wrapper1 ):

 def decorator(takes_a_function): @wraps(takes_a_function) def wrapper(*args, **kwargs): # logic here return takes_a_function(*args, **kwargs) return wrapper 
+7
source share

Ok, I solved this problem by reading this answer Route to view_func with the same flask decorators provided by @ will-hart

I just delete def wrapper(f) and now everything seems perfect. leaset has no grammar error.

 def requires_admin(f): @wraps(f) def wrapped(*args, **kwargs): #if blah blah: #return blah blah return f(*args, **kwargs) return wrapped 

Since I'm pretty new to the decorator and I don't know why. But hope this can help other ppl.

+4
source share

All Articles