import tornado.web
import tornado.ioloop
import tornado.auth
import tornado.escape
import tornado.options
from tornado.options import define, options
import mako.lookup
import mako.template
import os
define('port', default=8888, help='run on given port', type=int)
CURRENT_PATH= os.path.dirname(__file__)
TEMPLATE_PATH = os.path.join(CURRENT_PATH, 'templates')
STATIC_PATH = os.path.join(CURRENT_PATH, 'static')
LOOK_UP = mako.lookup.TemplateLookup(directories=[TEMPLATE_PATH,], module_directory='/tmp/mako',
output_encoding='utf-8', encoding_errors='replace')
class Application(tornado.web.Application):
def __init__(self):
handlers = [
(r'/', MainHandler),
]
settings = {
'cookie_secret':'',
'login_url':'',
'static_path':STATIC_PATH,
'xsrf_cookies':True,
}
super(Application, self).__init__(handlers, **settings)
class BaseHandler(tornado.web.RequestHandler):
def initialize(self, lookup=LOOK_UP):
'''
Set template lookup object, Defalut is LOOK_UP
'''
self._lookup = lookup
def get_current_user(self):
user = self.get_secure_cookie('user')
if not user:
return
return tornado.escape.json_decode(user)
def render_string(self, filename, **kwargs):
'''
Override render_string to use mako template.
Like tornado render_string method, this method
also pass request handler environment to template engin.
'''
try:
template = self._loolup.get_template(filename)
env_kwargs = dict(
handler = self,
request = self.request,
current_user = self.current_user,
locale = self.locale,
_ = self.locale.translate,
static_url = self.static_url,
xsrf_form_html = self.xsrf_form_html,
reverse_url = self.application.reverse_url,
)
env_kwargs.update(kwargs)
return template.render(**env_kwargs)
except:
# exception handler
pass
def render(self, filename, **kwargs):
self.finish(self.render_string(filename, **kwargs))
class MainHandler(BaseHandler):
@tornado.web.authenticated
def get(self):
self.render('index.html', messages=[])
class AuthLoginHandler(BaseHandler, tornado.web.GoogleMixin):
@tornado.web.asynchronous
def get(self):
if self.get_argument('openid.mode', None):
self.get_authenticated_user(self.async_callback(self._on_auth))
return
self.authenticate.redirect()
def _on_auth(self, user):
if not user:
raise tornado.web.HTTPError(500, 'Google authenticate failed')
self.set_secure_cookie('user', tornado.escape.json_encode(user))
self.redirect('/')
def main():
tornado.options.parse_command_line()
app = Application()
app.listen(options.port)
tornado.ioloop.IOLoop.instance().start()
if __name__ == '__main__':
main()
如上代码所示,只需要在派生的BaseHandler override initilize 和 render_string即可. 其他Request handler只要
继承自BaseHandler即可.这样就不仅可以使用性能高效的mako模板,而且还能使用tornado模板提供的一些功能.