Flask模板引擎Jinja2核心语法详解:从基础到高级应用

闻溪
闻溪
发布时间:2026-10-13 | 3人浏览过
原创

本文深入解析Flask内置的Jinja2模板引擎,系统介绍其核心语法。内容涵盖分隔符使用、变量与对象属性访问、内置过滤器(如safe、default、truncate)及测试函数、For循环中的特殊变量、空格控制机制、转义处理以及模板继承与宏定义。通过具体代码示例,帮助开发者掌握Jinja2在Web开发中的实际应用技巧。

Jinja2简介与常见问题

Jinja是构成Flask框架的核心模板引擎。即便你对它的具体运作机制尚不熟悉,但以下这些包含百分号和大括号的符号结构你一定并不陌生:


{% block body %}
 <ul>
 {% for user in users %}
  <li><a href="{{ user.url }}" rel="external nofollow" >{{ user.username }}</a></li>
 {% endfor %}
 </ul>
{% endblock %}

阅读《Flask Web开发》的读者通常能够编写出此类代码,但除了书中提及的基础知识外,掌握更多语法细节至关重要。本文将重点介绍Jinja2中常用且实用的语法与函数。若需系统性地深入了解,建议查阅官方文档:Jinja2 Documentation。

常见问题解答(FAQ)

在Jinja官方网站的FAQ栏目中,我筛选了三个用户关注度较高的问题(此处进行了简化翻译),供读者参考。

1、为何命名为Jinja?

名称“Jinja”源自日语中“神社”一词(Jinja),其英文对应词为“temple”。而“模板”的英文是“template”,两者发音相近。有趣的是,如果按音译逻辑,它或许也可以被命名为“Miao”(庙)。

2、Jinja的执行速度如何?

其性能表现与Mako模板引擎相当,但相比Genshi以及Django自带的模板引擎,速度提升了10至20倍。

3、在模板中引入逻辑判断(Logic)是否合理?

毫无疑问,模板中的逻辑判断应尽可能精简。然而,为了兼顾开发效率与用户体验,适度的逻辑处理是必要的。尽管如此,Jinja对模板中可执行的逻辑操作设有诸多限制。

出于对执行速度、代码可读性等多方面的考量,Jinja并不允许在模板中直接放置任意Python代码或执行所有Python表达式。这正是我们需要深入理解Jinja2语法规则的原因。

基础语法:分隔符与注释

分隔符(Delimiters)

Jinja2使用特定的分隔符来界定不同类型的指令: {% ... %} 用于定义语句(Statements) {{ ... }} 用于输出表达式(Expressions)的结果 {# ... #} 用于单行或多行注释 # ... ## 用于行内语句(Line Statements)

关于注释部分,这里展示的是单行注释的写法:


{#% for user in users %#}

以下是多行注释的示例:


{# note: commented-out template because we no longer use this
  {% for user in users %}
    ...
  {% endfor %}
#}

变量访问与属性获取

变量(Variables)

除了基础的字符串变量,Jinja2同样支持列表、字典及对象类型。你可以通过以下方式获取变量的值:


{{ mydict['key'] }}
{{ mylist[3] }}
{{ mylist[myintvar] }}
{{ myobj.somemethod() }}

访问变量属性主要有两种语法:


{{ foo.bar }}
{{ foo['bar'] }}

这两种方式在大多数场景下效果基本一致(深层差异在此暂不展开讨论)。

过滤器与测试函数详解

过滤器(Filter)

过滤器用于对变量进行转换或处理,通过竖线(|)与变量名分隔。


{{ items|join(', ') }}

以下是Jinja2常用的内置过滤器列表:

  • safe:渲染时不进行HTML转义
  • capitalize:将字符串首字母转换为大写
  • lower:将字符串转换为小写
  • upper:将字符串转换为大写
  • title:将字符串中每个单词的首字母转换为大写
  • trim:去除字符串首尾的空格
  • striptags:移除字符串中的HTML标签
  • default:为未定义的变量设置默认值。用法示例如下:

{{ my_variable|default('my_variable is not defined') }}
  • random(seq):从序列中随机返回一个元素
  • truncate(s, length=255, killwords=False, end='...'):截取指定长度的字符串,常用于生成文章摘要
  • format(value, *args, **kwargs):功能类似于Python的字符串格式化函数
  • length:若左侧为列表,返回元素数量;若为字符串,返回字符长度
  • ……

完整的过滤器列表请参考:http://jinja.pocoo.org/docs/dev/templates/#builtin-filters

测试(Tests)

Jinja2提供的测试功能允许在语句中对变量或表达式进行条件判断。判断变量时,需在变量后添加“is”关键字及测试名称,例如:


{% if user.age is equalto 42 %} {# 这里也可以写成... is equalto(42) #}
  Ha, you are 42!
{% endif %}

若测试需要传入参数,可以在测试名后加括号,也可以直接跟在后面。

常用的测试函数(未特别说明的均返回布尔值True或False):

  • defined:检查变量是否已定义
  • equalto:检查变量是否等于指定值
  • escaped:检查变量是否已转义
  • none:检查变量是否为None
  • sequence:检查变量是否为序列类型
  • string:检查变量是否为字符串类型
  • number:检查变量是否为数字类型
  • reverse:检查变量是否可反转
  • replace:检查变量是否包含可替换内容
  • ......

完整的测试列表及详细用法请参阅:Template Designer Documentation

循环控制与特殊变量

循环(Loop)

在For循环内部,可以使用一些特殊的内置变量,以下是几个常用示例:

  • loop.index:当前迭代次数(从1开始计数),常用于显示评论楼层号
  • loop.index0:同上,但迭代计数从0开始
  • loop.revindex:反向迭代次数(基数为1)
  • loop.revindex0:反向迭代次数(基数为0)
  • loop.length:序列的总长度
  • loop.first:判断当前元素是否为第一个
  • loop.last:判断当前元素是否为最后一个
  • ......

完整的循环变量列表请参考:http://jinja.pocoo.org/docs/dev/templates/#for

空格控制与转义处理

空格控制(Whitespace Control)

默认配置下的处理规则:

  1. 若语句末尾存在换行符,则会被去除;
  2. 其他空格保持原样保留。

具体表现为,以下代码段:


<div>
  {% if True %}
    yay
  {% endif %}
</div>

渲染后的结果如下所示:


<div>

    yay

</div>

Jinja2语句本身占用的空行、你手动输出的空格以及Tab缩进均会被保留。

若要去除Jinja2语句占用的空行,可以通过配置Jinja2的环境变量来实现:


app.jinja_env.trim_blocks = True
app.jinja_env.lstrip_blocks = True

或者,可以在语句块内部手动添加减号(注意减号与%之间不能有空格):


<div>
  {% if True -%}
    yay
  {%- endif %}
</div>

这两种方式产生的效果相同,渲染结果如下:


<div>
    yay
</div>

若在语句块的前后都加上减号:


<div>
  {%- if True -%}
    yay
  {%- endif -%}
</div>

渲染后的结果将变为:


<div>yay</div>

通过Jinja2提供的环境变量,你可以配置多种行为,例如修改分隔符(当与其他语言冲突时,可通过调整分隔符解决)。更多细节请参考:http://jinja.pocoo.org/docs/dev/api/#jinja2.Environment

转义(Escaping)

有时你需要原样输出Jinja2语句或分隔符。对于少量内容,可以使用变量表达式输出,例如输出一个左花括号分隔符:


{{ '{{' }}

对于大段内容,可以使用raw块进行包裹:


{% raw %}
  <ul>
  {% for item in seq %}
    <li>{{ item }}</li>
  {% endfor %}
  </ul>
{% endraw %}

模板继承与全局函数

模板继承(Template Inheritance)

你可以创建一个base.html作为基础模板,将导航栏、页脚、Flash消息、JavaScript或CSS文件等需要在所有页面中共享的内容放置在基模板中,并定义一个空块以容纳子模板的内容:


{% block content %}{% endblock %}

在其他子模板中,使用extends语句继承基模板,并将具体内容填入基模板中定义的对应空块:


{% extends "base.html" %}
{% block content %}
子模板的内容
{% endblock %}

若需向父模板中已定义的块追加内容,可使用super函数:


{% block sidebar %}
  <h3>Table Of Contents</h3>
  ...
  {{ super() }}
{% endblock %}

这种方式可以有效避免覆盖父模板中已定义的内容。

全局函数(Global Functions)

常用的全局函数包括:

  • range([start, ]stop[, step]):生成一个数字序列
  • lipsum(n=5, html=True, min=20, max=100):为模板生成Lorem Ipsum占位文本

详细的全局函数列表请参阅:Template Designer Documentation

其他内容

Jinja2的功能远不止于此,还包括行语句、控制流、表达式、宏定义等。由于篇幅限制,此处不再逐一赘述(撰写此类介绍性文章确实耗费精力……)。

具体内容请参阅文档的模板部分:

Template Designer Documentation

相关链接

Jinja官方网站:Jinja2 Documentation

Jinja2官方文档:Jinja2 Documentation

Jinja2文档模板章节:Template Designer Documentation

GitHub项目主页:pallets/jinja

以上就是本文的全部内容,希望能为你的学习提供帮助,也欢迎大家继续支持本站。

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表