【问题标题】:Decorator isn't getting arguments装饰器没有得到参数
【发布时间】:2017-11-19 06:57:37
【问题描述】:

我正在尝试在我的 Bottle 应用中添加一个 access_rights 装饰器,以便在访问路线时检查权限。但是,它没有获取修饰函数的参数,这会在尝试再次调用我的修饰函数时导致错误。

下面是使用装饰器的代码示例:

@route('/users')
@access_rights({'POST': ['admin']})
def users(user):
    pass

user 参数来自我编写的一个 Bottle 插件,该插件从随请求传递的令牌中获取用户。这是我现在的装饰器:

def access_rights(permissions):
    def decorator(f):    
        def wrapper(*args, **kwargs):
            # Check permissions rights here (not implemented yet)

            return f(*args, **kwargs)

        return wrapper

    return decorator

有了这个,我在执行GET /users 时得到TypeError: users() takes exactly 1 argument (0 given),这意味着argskwargs 都是空的。但是,当我按如下方式更改装饰器时,它可以工作:

def access_rights(permissions):
    def decorator(f):  
        return f

    return decorator

我没有经常使用装饰器,但据我了解,上面的两个实现都应该使用其原始参数调用users 函数,但由于某种原因,第一个没有得到参数。这是为什么呢?

【问题讨论】:

  • 这段代码对我有用。如果您的第二个装饰器语法有效,那么这意味着您没有将它与参数一起使用:即您只是在使用@access_rights 而不是@access_rights(whatever)
  • 也许某处检查了函数名称?在这种情况下,包装器上方的 @functools.wraps(f) 应该会有所帮助。
  • 你用的是py2还是py3?我不认为这有很大的不同,但我很好奇。
  • 不幸的是,已经尝试使用functools.wraps,但没有帮助。我确实忘记在我的问题中指定一些内容(在此评论之后进行编辑):user 参数来自 Bottle 插件;这会影响事情吗?
  • 使用 Python 2。

标签: python python-2.7 bottle python-decorators


【解决方案1】:

您的路由处理程序,函数users,需要一个参数。

但是你的装饰器access_rights,你包裹users,没有传递user参数;它只是传递它收到的任何参数(在这种情况下,没有任何参数,因此错误消息的“0 given”部分)。

一个例子应该有助于澄清。这是一个基于您的原始代码的小而完整的工作应用程序:

from bottle import route, Bottle

app = Bottle()

def access_rights(permissions):
    def decorator(f):
        def wrapper(*args, **kwargs):
            # Check permissions rights here (not implemented yet)

            the_user = 'ron'  # hard-coded for this example

            return f(the_user, *args, **kwargs)

        return wrapper

    return decorator


@app.route('/users')
@access_rights({'POST': ['admin']})
def users(user):
    return ['hello, {}'.format(user)]


app.run(host='127.0.0.1', port=8080, debug=True)

请注意,我所做的唯一重大更改是让access_rights 实际上传递了一个用户参数。 (它如何确定用户自然取决于您——大概是您在评论中提到的“尚未实现”部分)。

希望有帮助!

【讨论】:

  • 我完全理解 user 参数没有被传递,但这不是我的装饰者的工作。正如我的问题所述,user 参数是由插件生成和传递的,因此装饰器不应处理它。对我来说没有意义的是直接返回f,而不是使用传递的参数调用fwrapper,不会产生相同的结果。我在这里错过了什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-21
  • 2013-12-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-05
  • 2018-10-22
相关资源
最近更新 更多