2014-01-25 10 views
7

Ich brauche eine Python Dekorateur hinzufügen Wegfunktionen Flask, (im Grunde bearbeitet ich den Code aus here)Python Dekorateur mit Flask

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 

und es verwenden, wie dies in Ordnung sein wird:

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

Aber es verwendet, wie diese Fehler haben:

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

In Flask 0.10, ich Fehler wie diese zu erhalten (I updat nur ed von Flask 0,9 bis 0,10 und in Flask 0.9 gibt es keine Grammatikfehler wie diese):

@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 

ich zum Dekorateur Sachen ziemlich neu bin, wie kann ich diesen Fehler zu korrigieren?

+0

nicht zu 100% sicher, aber möglicherweise müssen Sie ein 'endpoint' Argument für die Strecke zur Verfügung zu stellen? Siehe http://stackoverflow.com/questions/17540754/route-to-view-func-with-same-decorators-flask –

+0

@ will-hart Ich habe gerade die Frage aktualisiert. Nur mit Parameter wird es Fehler geben. –

+0

@JamesKing ist es http://StackOverflow.com/Questions/28381560/most-effective-way-to-find-and-replace eine nette Frage. Sie haben Downvotes nur wegen des Mangels an Bemühungen. Komm mit Versuchen zurück und ich werde bereit sein, eine Antwort zu geben. –

Antwort

7

Sie haben zwei Wrapper-Funktionen, in denen Sie nur eine brauchen. Beachten Sie, dass jede Wrapper-Funktion ein Argument benötigt. Dies sollte ein Hinweis darauf sein, was passiert.

Sie haben:

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 

Wenn Sie dekorieren eine Funktion mit sich:

@decorator 
def my_function(*takes_multiple_arguments): 
    pass 

Dies entspricht:

def my_function(*takes_multiple_arguments): 
    pass 

my_function = decorator(my_function) 

aber tun decorator(my_function) kehrt wrapper1, die, wenn Sie Rückruf dauert ein Argument, take_a_function. Das ist eindeutig nicht das, was du willst. Sie möchten wrapper2 zurückgegeben. Wie in Ihrer Antwort ist die Lösung, die die äußere Umhüllung (wrapper1) zu entfernen:

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

    return wrapper 
4

Ok Ich löste dieses Problem, indem Sie diese Antwort zu lesen Route to view_func with same decorators "flask" gegeben @ Willen hart

ich einfach entfernen Sie das def wrapper(f) und jetzt alles in Ordnung zu sein scheint. kein Grammatikfehler.

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

Da bin ich ziemlich neu zu Dekorateur und ich weiß nicht warum. Aber hoffe das kann anderen helfen.

+1

Im Allgemeinen ein Dekorator mit keinen Argumenten neben der umhüllten Funktion benötigt nur eine innere Funktion. In Ihrem ersten Beispiel gibt 'requests_admin' eine Funktion zurück, die wiederum eine zweite Funktion übernimmt. Zwei Level Decorators sind für Dinge wie '@ app.route (extra_args)' oder '@wraps (f)'. – loki