带有Flask的Python装饰器

Jam*_*ing 8 python decorator flask

我需要为Flask路由函数添加一个python装饰器,(基本上我从这里编辑了代码)

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
Run Code Online (Sandbox Code Playgroud)

并使用它就像这样就可以了:

@app.route('/admin/action')
@requires_admin
def AdminAction():
#NO error if NO parameter
Run Code Online (Sandbox Code Playgroud)

但是使用它会有这样的错误:

@app.route('/admin/action/<int:id>')
@requires_admin
def AdminAction(id):
Run Code Online (Sandbox Code Playgroud)

在Flask 0.10中,我得到这样的错误(我刚从Flask 0.9更新到0.10,而在Flask 0.9中没有像这样的语法错误):

    @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
Run Code Online (Sandbox Code Playgroud)

我对装饰器的东西很新,我该如何纠正这个错误?

Joe*_*ett 8

你有两个包装函数,你只需要一个.请注意,每个包装函数都接受一个参数.这应该是发生了什么的线索.

你有:

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
Run Code Online (Sandbox Code Playgroud)

当你用它装饰一个函数时:

@decorator
def my_function(*takes_multiple_arguments):
   pass
Run Code Online (Sandbox Code Playgroud)

这相当于:

def my_function(*takes_multiple_arguments):
   pass

my_function = decorator(my_function)
Run Code Online (Sandbox Code Playgroud)

但是要做decorator(my_function)回报wrapper1,如果你回忆起一个论点,take_a_function.这显然不是你想要的.你想要wrapper2回来.在你的答案中,解决方案是删除外包装(wrapper1):

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

    return wrapper
Run Code Online (Sandbox Code Playgroud)


Jam*_*ing 5

好吧,我通过阅读@will-hart 给出的答案Route to view_func with samedecorators“flask”解决了这个问题

我只是删除了def wrapper(f),现在一切看起来都很好。至少没有语法错误。

from functools import wraps

def requires_admin(f):
    @wraps(f)
    def wrapped(*args, **kwargs):
        #if blah blah:
            #return blah blah
        return f(*args, **kwargs)
    return wrapped
Run Code Online (Sandbox Code Playgroud)

因为我对装饰器很陌生,我不知道为什么。但希望这可以帮助其他人。