我正在使用Flask-RESTful并尝试使用显示here
的技术来获取我的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并再次从validUUID获取acct
对象
我怎样才能做到这一点?
答案 0 :(得分:3)
authenticate
是一个装饰器 - 它接受一个函数并返回该函数的修改版本(通常通过包装函数并将其包装来实现)。
现在,包装器的问题在于它们通常在某些方面与原始函数完全不同 - 它们可能缺少文档字符串,错误__name__
(wrapper
而不是什么它应该被称为)和其他瑕疵。如果其他一些代码正在使用该额外信息,这可能很重要。 functools.wraps
是一个简单的函数,它将原始函数(此处为func
)中的此信息添加到包装函数中,因此它的行为更像原始函数。 (从技术上讲,它本身就是一个装饰器,这是一个令人困惑的部分,但你不必担心这个细节。只要知道它是一个很好的工具,将包装函数的属性复制到包装函数。)
因此,当你写
new_function = authenticate(old_function)
或更常见
@authenticate
def function(...)
new_function
看起来更像old_function
。