从RequestHandler继承的类中缺少self.async_callback

时间:2014-12-14 08:29:14

标签: python tornado

所以我现在正在学习Tornado网络框架,并且根据一本书中的一些示例,我设法通过OAuth2 / Google进行身份验证。它会重定向到Google以提示用户登录,但在登录后会向我抛出以下错误:

Traceback (most recent call last):
  File "C:\python27\lib\site-packages\tornado\web.py", line 1288, in _stack_context_handle_exception
    raise_exc_info((type, value, traceback))
  File "C:\python27\lib\site-packages\tornado\web.py", line 1475, in wrapper
    result = method(self, *args, **kwargs)
  File "C:\Users\enricojr\Downloads\Github\LearningTornado\grumble_login.py", line 8, in get
    self.get_authenticated_user(callback=self.async_callback(self._on_auth))
AttributeError: 'LoginHandler' object has no attribute 'async_callback'

在Github上检查Tornado源代码后,确实确实async_callback()方法已经消失了。有关如何处理这个的任何想法?我到目前为止使用Tornado的auth模块进行身份验证的每个例子都要求使用它,而且由于我是整个“异步网络编程”的新手,我现在还不太清楚我还能做些什么呢它

我的代码如下,Python 2.7和Tornado 4.0.2:

############################
# grumble_login.py
############################
from tornado.auth import GoogleMixin
from tornado.web import RequestHandler, asynchronous

class LoginHandler(RequestHandler, GoogleMixin):
    @asynchronous
    def get(self):
        if self.get_argument("openid.mode", None):
            self.get_authenticated_user(callback=self.async_callback(self._on_auth))
            return
        else:
            self.authenticate_redirect()

    def _on_auth(self, user):
        if not user:
            self.clear_all_cookies()
            raise tornado.web.HTTPError(500, "Google auth failed.")
        else:
            # the user id serves as the basis for 
            # all the data we store.
            self.set_secure_cookie('user_id', user['id'])
            self.redirect("/")

class LogoutHandler(RequestHandler):
    def get(self):
        self.clear_all_cookies()
        self.render("logout.html")

############################
# main.py
############################
import os

from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from tornado.web import Application
from tornado.options import define, options

from grumble_handlers import *
from grumble_user_handlers import *
from grumble_login import *


# /user/profile/<user> - leads to profile page
# /user/posts - leads to posts made by user

# /post/<id> - leads to a specific post
# /post/add - add post
# /post/edit - edit post
# /post/delete - delete post
# D$oP5lz3D$oP5lz3

TEMPLATE_PATH = os.path.join(os.path.dirname(__file__), "templates")
STATIC_PATH = os.path.join(os.path.dirname(__file__), "static")

if __name__ == "__main__":
    define("port", default=8000, help="run on the given port", type=int)

    settings_dict = {
        'cookie_secret': "GENERATE NEW KEY HERE",
        'template_path': TEMPLATE_PATH,
        'static_path': STATIC_PATH,
        'debug': True,
        'login_url': "/login",
    }

    general_handlers = [
        (r"/", IndexHandler),
        (r"/login", LoginHandler),
        (r"/logout", LogoutHandler)
    ]

    post_handler_list =[
        (r"/post/(\d+)", PostFetchHandler), # leads to a single post page
        (r"/post/add", PostAddHandler),
        (r"/post/edit", PostEditHandler),
        (r"/post/delete", PostDeleteHandler),
    ]

    user_handler_list = [
        (r"/user/(\d+)/posts", UserPostsHandler), # lists out all the posts by a given user
        (r"/user/(\d+)/profile", UserProfileHandler),
    ]

    master_handler_list = general_handlers + post_handler_list + user_handler_list

    app = Application(
        handlers=master_handler_list,
        **settings_dict
    )

    http_server = HTTPServer(app)
    http_server.listen(options.port)

    # GO TEAM GO
    IOLoop.instance().start()

############################
# grumble_handlers.py
############################
...
class IndexHandler(NotImplementedHandler):
    @authenticated
    def get(self):
        pass

1 个答案:

答案 0 :(得分:2)

遗憾的是,这本书早已过时。 async_callback was removed in Tornado 4 since it is no longer required。你可以这样做:

self.get_authenticated_user(callback=self._on_auth)

一旦你有了这个工作,我建议你关注the coroutine documents并学习如何使用“yield”:

user = yield self.get_authenticated_user()