当我使用 get_current_user()时,我需要异步检查 Redis (使用 tornado-redis )中的一些内容。
我正在做以下事情:
def authenticated_async(method):
@gen.coroutine
def wrapper(self, *args, **kwargs):
self._auto_finish = False
self.current_user = yield gen.Task(self.get_current_user_async)
if not self.current_user:
self.redirect(self.reverse_url('login'))
else:
result = method(self, *args, **kwargs) # updates
if result is not None:
yield result
return wrapper
class BaseClass():
@gen.coroutine
def get_current_user_async(self,):
auth_cookie = self.get_secure_cookie('user') # cfae7a25-2b8b-46a6-b5c4-0083a114c40e
user_id = yield gen.Task(c.hget, 'auths', auth_cookie) # 16
print(123, user_id)
return auth_cookie if auth_cookie else None
例如,我想使用 authenticated_async 装饰器:
class IndexPageHandler(BaseClass, RequestHandler):
@authenticated_async
def get(self):
self.render("index.html")
但我只在控制台 123 。
什么错了?如何解决?
谢谢!
更新
我已使用yield result
更新了代码。
在 auth_cookie 中,我有cfae7a25-2b8b-46a6-b5c4-0083a114c40e
。
然后我去终点站:
127.0.0.1:6379> hget auths cfae7a25-2b8b-46a6-b5c4-0083a114c40e
"16"
所以,
user_id = yield gen.Task(c.hget, 'auths', auth_cookie)
print(123, user_id)
必须返回
123 16
但它返回一个123
更新1
使用
class IndexPageHandler(BaseClass, RequestHandler):
@gen.coroutine
def get(self):
print('cookie', self.get_secure_cookie('user'))
user_async = yield self.get_current_user_async()
print('user_async', user_async)
print('current user', self.current_user)
self.render("index.html",)
在控制台中我有:
cookie b'cfae7a25-2b8b-46a6-b5c4-0083a114c40e'
123
user_async b'cfae7a25-2b8b-46a6-b5c4-0083a114c40e'
current user None
答案 0 :(得分:4)
get_secure_cookie()
返回一个字节字符串;因为使用b'
前缀打印出的cookie必须在Python 3上。在Python 3上,tornado-redis
似乎期望unicode字符串而不是字节字符串;任何不是unicode字符串的输入都将转换为str()
函数的输入。这会添加上面显示的b'
前缀,因此您要查询b'cfae7a25-2b8b-46a6-b5c4-0083a114c40e'
,而不是cfae7a25-2b8b-46a6-b5c4-0083a114c40e
解决方案是将Cookie转换为str
,然后再将其发送到redis:auth_cookie = tornado.escape.native_str(auth_cookie)
答案 1 :(得分:0)
看一下gen.Task的文档字符串:
获取一个函数(和可选的附加参数)并运行它 这些参数加上
callback
关键字参数。
c.hget是否接受回调参数?如果没有,回调将抛出异常,将来不会设置结果,因此print语句不会打印用户ID。
答案 2 :(得分:0)
答案回到你的包装程序中。
if result is not None:
yield result
你不想产生结果,但要回归"返回"它来自协程。但是,由于Python不允许您使用来自生成器的非空返回,因此您需要将其作为Tornado可以解包的包装异常引发,并将结果传递给调用者( get_current_user 强>)
if result is not None:
raise gen.Return(result)
完成后,您应该会发现它有效。