跬步 On Coding

在Tornado中使用jinja2模版引擎的简单方法

参考

实现

为了让自己的开发工具都能得到统一,所以想着以后不管是用Tornado也好,Bottle也好,模版引擎都开始用jinja2,所以更新了RSS Factory使用的模版引擎。

Google了下Tornado使用jinja2的方法,发现大部分人的实现方法都是重写ReaquestHandlerender方法,这样的虽然比较简单但是不利于保持Tornado的完整性,所以我使用参考文章中的方法。

通过查看代码发现,Tornado在渲染模版的时候会查找settings["template_loader"]这个实例,如果没有就用默认模版渲染,所以要做的就是在创建tornado.web.Application的时候定义template_loader

application = tornado.web.Application(
    template_loader=JinjaLoader(os.path.join(os.path.dirname(__file__), 'templates/')),
)

可以看到定义了template_loader并且以模版的目录为参数,接下来实现JinjaLoader

import threading
from tornado import template, web
import jinja2

class TTemplate(object):
    def __init__(self, template_instance):
        self.template_instance = template_instance

    def generate(self, **kwargs):
        return self.template_instance.render(**kwargs)

class JinjaLoader(template.BaseLoader):
    def __init__(self, root_directory, **kwargs):
        self.jinja_env = \
        jinja2.Environment(loader=jinja2.FileSystemLoader(root_directory), **kwargs)
        self.templates = {}
        self.lock = threading.RLock()

    def resolve_path(self, name, parent_path=None):
        return name

    def _create_template(self, name):
        template_instance = TTemplate(self.jinja_env.get_template(name))
        return template_instance

JinjaLoader继承自template.BaseLoader,通过_create_template方法最终把模版实例传给Tornado,但是Tornado中最后对模版使用字典渲染的时候使用的是generate方法, 而不是Jinja2默认的render方法,所以还需要TTemplate类来封装render这个过程。
这样我们就使用了tornado默认的接口而没有修改Tornado的模版实现逻辑来在Tornado中使用jinja2模版。