Using Mako with Tornado Web Server

January 1, 2010 | In: development, python, real time, tornado

So at work we have been focusing on real time web services a lot lately. Due to this I’ve been getting a chance to play with some awesome new technologies that really lend themselves to the real time web. One of these new technologies is the Tornado Web Server.

“Tornado is an open source version of the scalable, non-blocking web server and tools that power FriendFeed”

We’re using Mako to handle our templates (vs the template module that comes with Tornado). It’s super fast and feature rich and has good documentation. Bellow is a base class I wrote that illustrates how to render Mako templates from a Tornado RequestHandler class. It takes care of setting your template directory, template cache directory and your output encoding (utf-8).

Note: This example assumes that you have your template settings defined as tornado options but they could be very easily just hard coded in.

from tornado.web import RequestHandler
from mako.template import Template
from mako.lookup import TemplateLookup
from tornado.options import options

class BaseRequest(RequestHandler):
    def __init__(self, application, request, transforms=None):
        RequestHandler.__init__(self, application, request, transforms)
        self.lookup = TemplateLookup(directories=[options.template_dir], module_directory=options.mako_modules_dir, output_encoding='utf-8', encoding_errors='replace')

    def render_template(self,template_name, **kwargs):
        new_template = self.lookup.get_template(template_name)
        self.write(new_template.render(**kwargs))

Basically you would just derive your handlers from BaseRequest vs from RequestHandler and you will then be able to render your Mako templates via the render_template method.

Here is an example:

class ExampleHandler(BaseRequest):
    def get(self):
        self.render_template('example.html')

Shoot me a comment and let me know if you have any questions.

Bookmark and Share
  • SandraMillhouse
    I haven't heard of Mako before but after reading the post and the replies I think I'll give it a try. Thank you for the review.
    Sandra Millhouse @ Virtual servers UK
  • Hi,

    I was playing around with something similar, and I think you might be able to get better performance by using render_context, and creating a context with the current request handler. This way mako will write directly to your request, and not buffer into a string.

    Here's my render_template:

    def render_template(self, templatename, **kwargs):
    mytemplate = self.makolookup.get_template(templatename)
    context = Context(self)
    try:
    #r = mytemplate.render(h=helpers, **kwargs)
    mytemplate.render_context(context, **kwargs)
    except:
    exceptions.html_error_template().render_context(context)
    raise
  • ninjacipher
    Sweet! Nice work. Looks like you also did some work on adding session support. Very cool. We did something similar but instead of using memcached we store the sessions in mongodb. Anyway nice work. Love to see how it evolves.
  • Actually that was not my work - I just merged the session part from Milan Cermak's repository. And, you can store session data in files, files in directories, MySQL, Redis, Memcached and MongoDB. Plus the other extras, which are not on topic here. ^_~

    It's often better to join forces than be the lonely hero. I hope that with sessions I can get Ian Bicking's FormEncode validators integrated (disclosure: Iam one of FE authors), so we get an leightweight web-app framework similar to TurboGears.

    Currently I am stuck by the decision whether to use (in my own web-app) sessions at all or whether to let the clients store everything in cookies, to spare me the overhead of storing and retrieving session data. How do you think about this?
  • Update: Validators work (see the example in 'demos'), without the need for sessions.

    And Matt, see http://github.com/hudora/huBarcode so you can generate QR codes locally. ^_~
  • ninjacipher
    hmmm very interesting. Didn't notice the mongodb session handler in your repo. I'll have to go back and take a look at that. Totally agree about not being the lonely hero. I'm all about using the right tool for the right job, and if someone has done it already I'm happy to not reinvent the wheel. To be honest in my initial searching I couldn't find a session handler out there for mongodb so we just quickly hacked up our own.

    As for my opinion about sessions... it really depends on what kind of info your looking to store. If there is anything remotely sensitive you prob want to hold onto it yourself. If you need to persist something for a long period of time then cookies are the way to go. I tend to use a combo of both. To each his own though. :)

    Thx for the comments. I'll keep an eye on your repo. Interested to see where you end up with it. I think some of the things your working on will make Tornado a much more approachable option for a lot of developers.
  • Hi Matt. Some days ago I've integrated Mako templates similarly, but finally forked Tornado and replaced their templating engine completely (along with the uncommon i18n support, which is done by gettext now). See wmark/tornado at Github for more.
blog comments powered by Disqus

Flickr Pics

13th and washington NYC13th and 9th NYC1st st Jersey CityIMG_2813IMG_2814_2IMG_2816IMG_2815Photo_011908_001Photo_122807_001Photo_121107_001