正在加载...

tornado-3 controller

对于Tornado而言,MVC中的C就是它的Handler

Torando的Handler非常好写。只要继承自tornado.web.RequestHandler就好了

下面我统一的把Handler叫做Controller,因为习惯了这种叫法。

主要调用顺序

对于Controller的主要调用顺序如下:

  • __init__

这个是构造方法,如果需要在开始做一些事情的话,不推荐在这里。而推荐使用initialize

  • initialize

在这里可以做你想做的事情,比方说给这个Controller加入一些成员变量。例如:

class TestController(tornado.web.RequestHandler):

    def initialize(self): 
        self.uuid = uuid.uuid4().hex
  • prepare

在调用具体的get/post/...方法之前,会调用它。在这里加入加入一些权限控制。

比如说,除了登陆页面外,需要登陆成功了才能进行访问。

class TestController(tornado.web.RequestHandler):

    def prepare(self):
        if not self.request.uri.startswith(self.get_login_url()) and self.current_user is None:
            self.redirect(self.get_login_url())
  • get/post/put/delete/...

具体业务的方法

  • geterrorhtml

当有异常抛出的时候会调用它, 比方说,我们要渲染自己的错误页面

def get_error_html(self, status_code, **kwargs):
    return self.render_string('my_error.html', code=code, message=message, exception=exception)
  • finish

这个是一个很重要的方法,因为tornado最后总会调用finish一次,且仅仅调用一次。这个是由于它是异步框架的原因。

几个常用的方法

出去上面的调用顺序中的几个方法,常用的就是下面的了

  • getcurrentuser

得到当前用户,这个需要自己重写。一般的做法,从cookie中找到相应的session信息,再通过查session或者查db找到具体的用户

def get_current_user(self):
    username = self.get_secure_cookie("user")
    return self.db.get("select * from user where username = %s", username) if username else None
  • redirect

302跳转到某个地址 我一般喜欢封装一下,封装为:

def redirect_to(self, path, notice = None):
    self.notice(notice)
    return self.redirect(path)

这里的notice其实类似于rails中的flash。利用cookie实现的。代码如下:

def notice(self, value = None):
    if value is not None:
        _value = urllib2.quote(value.encode('utf-8'), 'true')
        self.set_cookie(self.FLASH_COOKIE_KEY, _value)
    else:
        v = self.get_cookie(self.FLASH_COOKIE_KEY, None)
        self.clear_cookie(self.FLASH_COOKIE_KEY)
        return urllib.unquote_plus(v).decode('utf-8') if v is not None else v
  • render

渲染某个页面的

同样我也细化封装一下:

def render_view(self, view_name, notice = None, **kwargs):
    kwargs.update(filters)
    _notice = notice or self.notice()
    return self.render(view_name, notice = _notice, **kwargs)

这样我就可以传入更多的默认渲染的东西

基本上就这些了