Jinja2:渲染模板继承?

11 投票
1 回答
12621 浏览
提问于 2025-04-16 18:44

我想用一个模板来生成一个结合了Jinja2和Markdown的页面,模板大概是这样的:

{% block title %}{{ title }}{% endblock %}

# {{ title[0] }}
# {{ title[1] }}

## Introduction

我可以让上面的代码正常生成HTML,但因为我在做一个自定义的创作应用,所以我希望能为每种类型的内容定义主模板。

当我尝试通过扩展一个主模板template.html来渲染上面的页面时:

{% extends 'template.html' %}

{% block title %}{{ title }}{% endblock %}

# {{ title[0] }}
# {{ title[1] }}

## Introduction

我遇到了一个错误:

Traceback (most recent call last):
  File "compiler.py", line 55, in <module>
    template = Template(text).render(parser.vars)
  File "/usr/lib/python2.7/site-packages/jinja2/environment.py", line 891, in render
    return self.environment.handle_exception(exc_info, True)
  File "<template>", line 1, in top-level template code
TypeError: no loader for this environment specified

你可以看到问题出在这一行:template = Template(text).render(parser.vars)

有没有办法让我渲染上面的模板代码,同时又能扩展template.html呢?

1 个回答

21

Jinja的渲染器需要知道怎么加载 template.html 文件,所以你需要给 Environment 提供一个模板加载器的实例。

比如说,假设 page.htmltemplate.html 文件都在当前目录下:

from jinja import FileSystemLoader
from jinja.environment import Environment

env = Environment()
env.loader = FileSystemLoader('.')
tmpl = env.get_template('page.html')
print tmpl.render(parser.vars)

更新 - 你可以创建一个自定义的模板加载器,或者使用在 jinja2.loaders 中定义的现有类。例如,DictLoader 会在一个 dict() 实例中查找 template.html,并把找到的值当作模板数据。其实从任何地方加载模板都应该很简单(比如从内存缓存、mysql、redis、一个Python对象等等)。

使用 DictLoader 的例子:

pages = ('template.html', 'page.html')
templates = dict((name, open(name, 'rb').read()) for name in pages)
env.loader = DictLoader(templates)

page.html

{% extends "template.html" %}

撰写回答