Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python decorator in flask

Here is my example:

from flask import Flask

app = Flask(__name__)
def add1(f):
    def inner(*args, **kwargs):
        return str(f(*args, **kwargs))+'1'
    return inner


@app.route('/')
@add1
def hello1():
    return "hello1";

@app.route('/hello2')
@add1
def hello2():
    return "hello2";


if(__name__ =='__main__'):
    app.run()

When I run 127.0.0.1:5000, I expect to get "hello11", but I get "hello21", why?

like image 511
Yang Avatar asked Jul 16 '12 03:07

Yang


1 Answers

The problem is that Flask keeps track of the functions by name, and because the functions getting passed to app.route(path) are both called inner, the second one (hello2) overwrites the first. To fix this, you will need the name of the inner function to be changed to the name of the function it is decorating. You can change the decorator to

def add1(f):
    def inner(*args, **kwargs):
        return str(f(*args, **kwargs))+'1'
    inner.__name__ = f.__name__
    return inner

which will work, but is not as elegant as the standard library solution,

from functools import wraps

def add1(f):
    @wraps(f)
    def inner(*args, **kwargs):
        return str(f(*args, **kwargs))+'1'
    return inner

The wraps decorator not only fixes the name, but the docstring, the file, and the attribute dictionary.

like image 199
Abe Karplus Avatar answered Sep 19 '22 10:09

Abe Karplus