python flask decorator

python decorator



Decorador de Python con Frasco (2)

Necesito agregar un decorador de Python a las funciones de ruta de Flask (básicamente edité el código desde aquí )

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

y usarlo así estará bien:

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

Pero úsalo así tendréis un error:

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

En Flask 0.10, recibo errores como este (acabo de actualizar de Flask 0.9 a 0.10, y en Flask 0.9 no hay errores de gramática como este):

@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

Soy bastante nuevo en materia de decoración, ¿cómo puedo corregir este error?


Tienes dos funciones de contenedor donde solo necesitas una. Tenga en cuenta que cada función de contenedor toma un argumento. Esto debería ser una pista de lo que está sucediendo.

Tienes:

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

Cuando decora una función con ella:

@decorator def my_function(*takes_multiple_arguments): pass

Esto es equivalente a:

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

pero haciendo decorator(my_function) devuelve wrapper1 , que si lo recuerdas toma un argumento, take_a_function . Esto claramente no es lo que quieres. Quieres que wrapper2 devuelto. Como en su respuesta, la solución es eliminar la envoltura externa ( wrapper1 ):

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


Ok, resolví este problema leyendo esta respuesta Route to view_func con el mismo "matraz" de decoradores dado por @ will-hart

Simplemente elimino la def wrapper(f) y todo parece estar bien ahora. al menos no hay error gramatical.

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

Ya que soy bastante nuevo como decorador y no sé por qué. Pero espero que esto pueda ayudar a otras personas.