我正试图绕过龙卷风。我正在编写一个由mongodb支持的聊天应用程序,我正在使用motor
进行非阻塞访问。
我想要实现的目标是:
motor
从mongo异步拉取用户记录的装饰器motor
的mongo异步调用来检索'ChatRoom'记录。我有装饰师1.工作(基本上取自http://tornadogists.org/5251927/):
def authenticated_async(f):
@functools.wraps(f)
@gen.engine
def wrapper(self, *args, **kwargs):
self.current_user = yield gen.Task(self.get_current_user_async)
if self.current_user:
logging.info("User '%s' (%s) successfully authenticated" %
(self.current_user['username'],
self.current_user['_id']))
f(self, *args, **kwargs)
else:
raise tornado.web.HTTPError(401, "User not authenticated, "
"aborting")
return wrapper
麻烦的是,对于第二个装饰者,我需要访问self.current_user
。因为这是在异步回调中设置的,所以当我进入validation
装饰器时它就不可用(即在auth装饰器完成之前调用验证装饰器)。
我是否不可能以这种方式使用异步函数的装饰器?在确保self.current_user
为True之后,我是否只需要在上述方法中调用验证方法,这样更像回调?
我希望我的Handler中的方法能够包含这两个装饰器,所以我可以在其他地方重复使用它们,即:
class ChatSocketHandler(tornado.websocket.WebSocketHandler):
@gen.coroutine
@validate_invitation_access_async
@authenticated_async
def open(self, invitation_id):
# do stuff here...
更新
实际上,没有依赖性。 user_id作为参数提供,可用于并行运行两个装饰器 - 一个用于确认身份验证,另一个用于查看具有该ID的用户是否允许访问该空间。 open()
方法只会在self.auth_check == True and self.room_check == True
。
可以在异步装饰器完成之前调用open()
吗?
答案 0 :(得分:0)
您需要切换装饰器的顺序,以便validate_invitation_access_async
包装器可以访问current_user:
@authenticated_async
@validate_invitation_access_async
def open(self, invitation_id):
# do stuff here...
然后validate_invitation_access_async
中的包装器是authenticated_async
中的“f”:它是在设置self.current_user之后调用的。请注意,您不需要额外的gen.engine
装饰器,所有包装器都已经是引擎。你的包装器可能就像:
def validate_invitation_access_async(f):
@gen.engine
def wrapper(self, *args, **kwargs):
# ... use Motor to see if user is authorized ...
# if not, log and redirect. otherwise:
f(self, *args, **kwargs)
您还应该更新代码以使用Tornado 3的gen.coroutine而不是gen.engine:它更清晰。但我把它留作练习。