>>> from env_helper import info; info()
页面更新时间: 2024-01-20 17:15:30
运行环境:
    Linux发行版本: Debian GNU/Linux 12 (bookworm)
    操作系统内核: Linux-6.1.0-17-amd64-x86_64-with-glibc2.36
    Python版本: 3.11.2

5.1. Jinja2模板

jinja2是python中的一个优秀的模板语言,类似于django的模板。它的速度快,安全,目前被各种框架被广泛使用。 官网地址:http://jinja.pocoo.org/

它的一些特性:

  • 沙箱执行机制很安全

  • 通过对HTML进行自动转义防止XSS攻击

  • 模板继承

  • 实时编译为最优化的python代码,使得它运行速度非常快

  • 可选的模板预编译

  • 容易调试,错误行数直接指向模板中的行

  • 配置文件语法也是模板

安装

非常简单,一条命令搞定:

pip install jinja2

5.1.1. 基本使用

通过创建一个Template类,不过这种方法不是推荐方式:

>>> from jinja2 import Template
>>> template = Template('Hello {{ name }}!')
>>> template.render(name='John Doe')
'Hello John Doe!'

Python3的支持

目前是支持Python3.3或以上版本的,所有单元测试都能通过,但是可能还会有隐藏的小bug。

5.1.2. 基础

Jinja2使用一个中心对象叫模板环境Environment,用它来存储陪着和全局对象, 然后使用它从文件或其他地方加载模板。就算刚刚的Template例子,一个Environment对象也被隐式的创建了。

大多数框架会在程序启动时创建一个Environment对象,用它来加载模板。

最简单的陪着Jinja2和加载模板的方式类似下面:

>>> from jinja2 import Environment, PackageLoader
>>> env = Environment(loader=PackageLoader('tutoapp', 'templates'))

它会创建一个Environment,使用了默认配置和一个在yourapp包的templates文件夹下面搜索模板的加载器。 你还可以使用其他的加载器,或者自定义加载器,来从数据库或其他地方加载模板。

要想加载到一个模板,只需使用get_template()方法

>>> uu = env.list_templates()
>>> template = env.get_template('mytpml.jinja2')
>>> template.render(the='variables', go='here')
'<body>n    n</body>'

Unicode Jinja2内部使用Unicode,所以传给render方法的参数必须是unicode对象,另外换行符是unix的’:raw-latex:`\n`’。

Jinja2的模板默认编码是utf-8,一些库会严格检查str类型比如datetime.strftime,它不接受unicode参数。 所以Jinja2对于ascii字符串返回str,其他的返回unicode,比如:

>>> m = Template(u"{% set a, b = 'foo', 'föö' %}").module
>>> m.a
'foo'
>>> m.b
'föö'

自动转换

推荐的做法是开启 Autoescape Extension扩展,下面是一个推荐的启动配置方案,对于.html,.htm和.xml的模板开启自动转换, 对于其他的禁止自动转换:

>>> def guess_autoescape(template_name):
>>>     if template_name is None or '.' not in template_name:
>>>         return False
>>>     ext = template_name.rsplit('.', 1)[1]
>>>     return ext in ('html', 'htm', 'xml')
Version 3.1.0

Released 2022-03-24

Drop support for Python 3.6. #1534

Remove previously deprecated code. #1544

WithExtension and AutoEscapeExtension are built-in now.
>>> env = Environment(autoescape=guess_autoescape,
>>>                   loader=PackageLoader('tutoapp') )

5.1.3. 加载器

加载器用来某个源比如文件来加载模板。Environment对象会将编译后的模块放到内存中, 类似于python中的sys.modules,但是不同之处在于如果模板更改了它会自动查询加载。

所有加载器都继承自BaseLoader,如果你想定义自己的加载器,就写个子类,重写它的get_source方法即可。 一个基本的从文件加载模板的加载器像下面这样:

>>> from jinja2 import BaseLoader, TemplateNotFound
>>> from os.path import join, exists, getmtime
>>>
>>> class MyLoader(BaseLoader):
>>>
>>>     def __init__(self, path):
>>>         self.path = path
>>>
>>>     def get_source(self, environment, template):
>>>         path = join(self.path, template)
>>>         if not exists(path):
>>>             raise TemplateNotFound(template)
>>>         mtime = getmtime(path)
>>>         with file(path) as f:
>>>             source = f.read().decode('utf-8')
>>>         return source, path, lambda: mtime == getmtime(path)

内置的一些加载器:

jinja2.FileSystemLoader(searchpath, encoding='utf-8', followlinks=False)       #文件系统
jinja2.PackageLoader(package_name, package_path='templates', encoding='utf-8') #包
jinja2.DictLoader(mapping)                                                     #字典,没啥用
jinja2.FunctionLoader(load_func)                                               #通过一个函数来加载
jinja2.PrefixLoader(mapping, delimiter='/')                                    #有前缀的
jinja2.ChoiceLoader(loaders)                                                   #多个加载器,找到第一个匹配
jinja2.ModuleLoader(path)                                                      #预编译好的模块

自定义过滤器

>>> def datetimeformat(value, format='%H:%M / %d-%m-%Y'):
>>>     return value.strftime(format)

然后注册到环境中

>>> env.filters['datetimeformat'] = datetimeformat

5.1.4. 模板语法

介绍完API后,开始介绍模板设计语法 基础

下面是一个典型的模板:

<!DOCTYPE html>
<html lang="en">
<head>
    <title>My Webpage</title>
</head>
<body>
    <ul id="navigation">
    {% for item in navigation %}
        <li><a href="{{ item.href }}">{{ item.caption }}</a></li>
    {% endfor %}
    </ul>

    <h1>My Webpage</h1>
    {{ a_variable }}

    {# a comment #}
</body>
</html>

默认的语法配置是这样的,你可以自己自定义:

  • {% raw %}{% ... %}{% endraw %} 这个是语句

  • {% raw %}{{ ... }}{% endraw %} 这个是表达式,打印模板输出

  • {% raw %}{# ... #}{% endraw %} 这个是注释部分,不会输出

  • #  ... # 这个是行语句