将函数传递给 class 并将其用作 class 方法的装饰器
passing function into a class and using it as a decorator of class methods
首先我创建了一些我想到处使用的用户管理功能,并将它们绑定到 cherrypy,我想我可以在其他地方导入 cherrypy,它们就会在那里。其他函数在不用作装饰器时似乎可以通过这种方式导入。
from user import validuser
cherrypy.validuser = validuser
del validuser
那没有用,所以接下来我尝试将函数从 class页数:
class Root:
analyze = Analyze(cherrypy.validuser) #maps to /analyze
并且在分析 class 中,我提到了它们。这适用于普通功能,但不适用于装饰器。为什么不呢?
class Analyze:
def __init__(self, validuser):
self.validuser = validuser
@cherrypy.expose
@self.validuser(['uid'])
def index(self, **kw):
return analysis_panel.pick_data_sets(user_id=kw['uid'])
我卡住了。我如何传递函数并将它们用作装饰器。我不想像这样包装我的函数:
return self.validuser(analysis_panel.pick_data_sets(user_id=kw['uid']),['uid'])
谢谢。
ADDED/EDITED:这是装饰器正在做的事情,因为作为一个单独的问题,我认为它没有正确地将 user_id 添加到 kwargs
def validuser(old_function, fetch=['uid']):
def new_function(*args, **kw):
"... do stuff. decide is USER is logged in. return USER id or -1 ..."
if USER != -1 and 'uid' in fetch:
kw['uid'] = user_data['fc_uid']
return old_function(*args, **kw)
return new_function
只有传入的 kwargs 出现在 new_function 的 kwargs 中。我尝试添加的任何内容都不存在。 (我所做的似乎在这里工作 How can I pass a variable in a decorator to function's argument in a decorated function?)
function/method定义在class中,用实例变量装饰它没有意义,因为它不会对每个实例都是相同的装饰器。
您可以考虑使用property
在访问时创建装饰方法:
@property
def index(self):
@cherrypy.expose
@self.validuser(['uid'])
def wrapped_index(**kw):
return analysis_panel.pick_data_sets(user_id=kw['uid'])
return wrapped_index
您也可以考虑尝试应用 lru_cache
来为每个实例保存方法,但我不确定如何将其应用到 属性。
在 CherryPy 中处理这种情况的正确方法是 a tool 并在您网站上需要身份验证的部分启用该工具。考虑首先创建此用户身份验证工具:
@cherrypy.tools.register('before_handler')
def validate_user():
if USER == -1:
return
cherrypy.request.uid = user_data['fc_uid']
注意 'register' decorator was added in CherryPy 5.5.0.
然后,无论您希望在何处验证用户,都可以使用以下工具装饰处理程序:
class Analyze:
@cherrypy.expose
@cherrypy.tools.validate_user()
def index(self):
return analysis_panel.pick_data_sets(user_id=cherrypy.request.uid)
或者在您的 cherrypy 配置中,启用该工具:
config = {
'/analyze': {
'tools.validate_user.on': True,
},
}
首先我创建了一些我想到处使用的用户管理功能,并将它们绑定到 cherrypy,我想我可以在其他地方导入 cherrypy,它们就会在那里。其他函数在不用作装饰器时似乎可以通过这种方式导入。
from user import validuser
cherrypy.validuser = validuser
del validuser
那没有用,所以接下来我尝试将函数从 class页数:
class Root:
analyze = Analyze(cherrypy.validuser) #maps to /analyze
并且在分析 class 中,我提到了它们。这适用于普通功能,但不适用于装饰器。为什么不呢?
class Analyze:
def __init__(self, validuser):
self.validuser = validuser
@cherrypy.expose
@self.validuser(['uid'])
def index(self, **kw):
return analysis_panel.pick_data_sets(user_id=kw['uid'])
我卡住了。我如何传递函数并将它们用作装饰器。我不想像这样包装我的函数:
return self.validuser(analysis_panel.pick_data_sets(user_id=kw['uid']),['uid'])
谢谢。
ADDED/EDITED:这是装饰器正在做的事情,因为作为一个单独的问题,我认为它没有正确地将 user_id 添加到 kwargs
def validuser(old_function, fetch=['uid']):
def new_function(*args, **kw):
"... do stuff. decide is USER is logged in. return USER id or -1 ..."
if USER != -1 and 'uid' in fetch:
kw['uid'] = user_data['fc_uid']
return old_function(*args, **kw)
return new_function
只有传入的 kwargs 出现在 new_function 的 kwargs 中。我尝试添加的任何内容都不存在。 (我所做的似乎在这里工作 How can I pass a variable in a decorator to function's argument in a decorated function?)
function/method定义在class中,用实例变量装饰它没有意义,因为它不会对每个实例都是相同的装饰器。
您可以考虑使用property
在访问时创建装饰方法:
@property
def index(self):
@cherrypy.expose
@self.validuser(['uid'])
def wrapped_index(**kw):
return analysis_panel.pick_data_sets(user_id=kw['uid'])
return wrapped_index
您也可以考虑尝试应用 lru_cache
来为每个实例保存方法,但我不确定如何将其应用到 属性。
在 CherryPy 中处理这种情况的正确方法是 a tool 并在您网站上需要身份验证的部分启用该工具。考虑首先创建此用户身份验证工具:
@cherrypy.tools.register('before_handler')
def validate_user():
if USER == -1:
return
cherrypy.request.uid = user_data['fc_uid']
注意 'register' decorator was added in CherryPy 5.5.0.
然后,无论您希望在何处验证用户,都可以使用以下工具装饰处理程序:
class Analyze:
@cherrypy.expose
@cherrypy.tools.validate_user()
def index(self):
return analysis_panel.pick_data_sets(user_id=cherrypy.request.uid)
或者在您的 cherrypy 配置中,启用该工具:
config = {
'/analyze': {
'tools.validate_user.on': True,
},
}