2014-01-25 50 views
7

我需要添加一个python装饰器烧瓶路线的功能,(基本上我编辑从here代码)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 

,并使用它像这将是确定:

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

但使用这样就会有错误:

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

在瓶0.10,我得到这样的错误(我只是updat从瓶0.9编至0.10,并在瓶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 

我非常新的东西装饰,我该如何纠正这一错误?

+0

不是100%肯定,但可能你需要提供一个'endpoint'参数的路线?见http://stackoverflow.com/questions/17540754/route-to-view-func-with-same-decorators-flask –

+0

@ will-hart我刚刚更新了这个问题。只有参数会有错误。 –

+0

@JamesKing它的http://stackoverflow.com/questions/28381560/most-effective-way-to-find-and-replace一个很好的问题。你只是因为缺乏努力而感到低落。回来尝试,我会准备好提供一个答案。 –

回答

7

你有两个包装函数,你只需要一个。请注意,每个包装函数都带有一个参数。这应该是正在发生的事情的线索。

您有:

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 

当你装饰功能吧:

@decorator 
def my_function(*takes_multiple_arguments): 
    pass 

这相当于:

def my_function(*takes_multiple_arguments): 
    pass 

my_function = decorator(my_function) 

但这样做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 
4

好吧,我通过阅读@ WILL - 哈特

我只是删除了def wrapper(f),一切现在看来罚款给出这个答案Route to view_func with same decorators "flask"解决了这个问题。至少不会出现语法错误。

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

因为我对装饰者来说很新,我不知道为什么。但希望这可以帮助其他人。

+1

一般而言,除了包装函数外,没有参数的装饰器只需要一个内部函数。在你的第一个例子中,require_admin函数返回一个函数,而函数又取得第二个函数。两个级别的装饰器适用于像'@ app.route(extra_args)'或'@wrap(f)'这样的东西。 – loki