0

我正在使用 Flask-RESTful 并尝试使用此处显示的技术让我的 REST 端点

主要代码是

def authenticate(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        if not getattr(func, 'authenticated', True):
            return func(*args, **kwargs)

        acct = basic_authentication()  # custom account lookup function

        if acct:
            return func(*args, **kwargs)

        restful.abort(401)
    return wrapper


class Resource(restful.Resource):
    method_decorators = [authenticate]   # applies to all inherited resources

我也这样做,它似乎有效,但我不确定会发生什么@wraps
目前对我来说似乎很神奇,我不明白以下内容

a.) 似乎被包装的函数@wraps被传递给了包装器,那么包装器返回的是什么?

可能的答案:最初传递给函数的所有东西?

如果是的话,我怎样才能传递更多的信息,比如acct包含所有内容的对象,以便我的函数接收帐户对象并且我不必为它进行数据库获取?

更新 基于示例,我的休息端点看起来像

class UserResource(RestResource):
    def get(self, uuid):
        return {'method': 'get user -> ' + uuid}

我称之为

curl -X GET http://127.0.0.1:5000/users/validUUID

现在,当我的每个请求都经过身份验证时,我会查看是否存在有效acct对象,如果存在,我将控制权委托给端点

问题
由于我实际上是在进行一次数据库调用以找出acct对象,因此是否可以在找到有效对象时将其传递给端点acct

这样会发生两件事
a.) 我知道调用已通过身份验证
b.) 我重用acct可用于进一步工作的对象,而不是再次调用 DB 并再次acct从 validUUID 获取对象

我怎样才能做到这一点?

4

1 回答 1

3

authenticate是一个装饰器——它接受一个函数并返回该函数的修改版本(通常通过包装函数和包装它来实现)。

现在,包装器的问题在于它们在某些方面的行为通常与原始函数不完全相同——它们可能缺少文档字符串、错误__name__wrapper而不是应该调用的名称)以及其他缺陷。如果其他代码正在使用该额外信息,这可能很重要。functools.wraps是一个简单的函数,它将原始函数(此处为func)的信息添加到包装函数中,因此它的行为更像原始函数。(从技术上讲,它本身就是一个装饰器,这是令人困惑的部分,但您不必担心那个细节。只要知道它是一个很好的工具,可以将属性从包装函数复制到包装函数)。

因此,当你写

new_function = authenticate(old_function)

或更常见的

@authenticate
def function(...)

new_function看起来会更像old_function

于 2013-04-09T04:35:27.217 回答