我正试图绕过龙卷风。我正在编写一个由 mongodb 支持的聊天应用程序,我正在使用motor
它进行非阻塞访问。
我想要实现的是:
- 创建一个装饰器,用于
motor
从 mongo 异步拉取用户的记录 - 验证他们的凭据(用户名和令牌)
- 创建另一个装饰器,检查上面 1. 中检索到的 user_id 是否被允许访问聊天室。这需要另一个异步调用 mongo
motor
来检索“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()
在异步装饰器完成之前调用吗?