一篇文章搞懂Jinja2 Template Engine 模版引擎

Flask和Django,以及其它很多Python框架,都默认使用Jinja2来作为模版引擎。

在Python中,什么是模版?就是在一个静态HTML加入一些类似变量的标签,然后引擎在渲染这个HTML时候会动态的把变量填入内容,生成一个最终的HTML。
什么是模版引擎?其实就是一种能解析类似Python语言的标记语言的解释器。

比如我们在HTML模版中输入一个<p> {{ post.title }} </p>,显然这不是真正的HTML语法。但是当Jinja2解释器读取到{{ ...}}后知道里面是一个变量,那么就把这个变量替换为真正的值,最后翻译出来就变成了<p> 大标题 </p>这样的HTML内容。

Jinja2是一个模版语言,只是类似Python,比较符合Python语法,但不完全相同!

所有的模版引擎,实际上都差不多,不管是基于VBS语言的ASP模版,还是基于PHP语言的PHP模版,都不是与原本语言一摸一样,而只是做到尽量一样而已。

Jinja2语言基础

注意:Jinja2模版语言,是不区分缩进的,和纯python不同。实际上所有模版语言都不区分缩紧。

常用标记:

  • 注释:{# 这是注释 #}
  • 变量:{{ post.title }},或字典元素{{your_dict['key']}},或列表{{your_list[0]}}
  • 多行代码块:{% 开始 %} HTML标签 {% 结束 %}

示例:

{% if user %}
    {{ user }}
{% else %}
    hello!
    {% for index in indexs %}
        {{ index }} 
{% endfor %}

Jinja2 Filter 过滤器 (即函数)

一个filter过滤器的本质就是一个function函数。使用格式为:变量名 | 函数
它做到的就是,把变量传给函数,然后再把函数返回值作为这个代码块的值。

如:

<!-- 带参数的 -->
{{变量 | 函数名(*args)}}

<!-- 不带参数可以省略括号 -->
{{变量 | 函数名}}

链式调用(管道式):
和命令行的pipline管道一样,可以一次调用多个函数(过滤器),如:

{{ "hello world" | reverse | upper }}

文本块调用(将中间的所有文字都作为变量内容传入到过滤器中):

{% filter upper %}
    一大堆文字
{% endfilter %}

Jinja2常用内置函数(过滤器)

字符串操作:

safe:禁用转义
<p>{{ '<em>hello</em>' | safe }}</p>

capitalize:把变量值的首字母转成大写,其余字母转小写
<p>{{ 'hello' | capitalize }}</p>

lower:把值转成小写
<p>{{ 'HELLO' | lower }}</p>

upper:把值转成大写
<p>{{ 'hello' | upper }}</p>

title:把值中的每个单词的首字母都转成大写
<p>{{ 'hello' | title }}</p>

reverse:字符串反转
<p>{{ 'olleh' | reverse }}</p>

format:格式化输出
<p>{{ '%s is %d' | format('name',17) }}</p>

striptags:渲染之前把值中所有的HTML标签都删掉
<p>{{ '<em>hello</em>' | striptags }}</p>

truncate: 字符串截断
<p>{{ 'hello every one' | truncate(9)}}</p>

列表操作:

first:取第一个元素
<p>{{ [1,2,3,4,5,6] | first }}</p>

last:取最后一个元素
<p>{{ [1,2,3,4,5,6] | last }}</p>

length:获取列表长度
<p>{{ [1,2,3,4,5,6] | length }}</p>

sum:列表求和
<p>{{ [1,2,3,4,5,6] | sum }}</p>

sort:列表排序
<p>{{ [6,2,3,1,5,4] | sort }}</p>

Jinja2 Macro 宏 (自定义函数)

Jinja2是允许自定义函数的,这样在模版中可以重复利用这个自定义函数。Jinja2称之为Macro宏。

定义方法:

{% macro 函数名(参数) %}
    具体的HTML内容
{% endmacro %}

<!-- 使用 -->
{{ 函数名(参数) }}

<!-- 或作为过滤器 -->
{{ 变量 | 函数名(参数) }}

关于Jinja2自定义函数的context上下文和环境变量的问题:
Jinja2的自定义函数“宏”,本身是没法像filter过滤器函数一样使用上下文和环境变量的。
不过可以加上@contextfilter装饰器达到同样的效果。

导入另一个文件的自定义函数“宏”:
假设在macro.html文件中我们定义了一个函数func()
那么现在我们可以在另一个文件reference.html中像python导入模块一样导入它:

{% import 'macro.html' as module %}
{{ module.func() }}

Include 模版引用

Include是我们常用的操作,即定义一个框架模版(父模版),然后一个一个指定性的把子模版引入进来。

框架模版frame.html如下:

{% include 'header.html' %}

{% include 'body.html' %}

{% include 'footer.html' %}

Extend 模版继承

我们可以在一个父模版中定义一个block代码块,然后在另一个子模版中“继承”这个父模版,并重写这个block代码块。
不过一般模版中的父模版,都只是留出一个block空位,里面不写东西,特意等子模版来实现。

假设现在有一个父模版parent.html

{% block HEADER %}
    页头部分的HTML内容。
{% endblock HEADER %}

{% block BODY %}
    正文部分的HTML内容。
{% endblock BODY %}

{% block FOOTER %}
    页脚部分的HTML内容。
{% endblock FOOTER %}

其中定义了三个block,页头、正文和页脚。

然后我们就可以定义一个模版child.html来继承父模版,并且只重写BODY部分:

{% extends 'parent.html' %}
{% block BODY %}
    由子页面重写改写的的HTML内容,替换父页面的BODY。。。
{% endblock BODY %}

扩展完成后,我们最终得到的结果是:

{% block HEADER %}
    页头部分的HTML内容。
{% endblock HEADER %}

{% block BODY %}
    由子页面重写改写的的HTML内容,替换父页面的BODY。。。
{% endblock BODY %}

{% block FOOTER %}
    页脚部分的HTML内容。
{% endblock FOOTER %}

Jinja2模版引用Flask路由中的内容

在Flask应用Jinja2模版时,在模版中可以直接调用Flask app中的一些公用变量和方法。

引用Flask的request对象:

<p> {{ request.url }} </p>
<p> {{ request.form.get('name') }} </p>

引用Flask的url_for(...)方法:

<!-- 它会返回我们定义的路由`app.route('/index')`所对应的URL -->
<p> {{ url_for('index') }} </p>

<!-- 它会返回我们定义的路由`app.route('/post/{post_id}')`所对应的URL -->
<p> {{ url_for('post', post_id='127') }} </p>

在模版中,我们可以引用get_flashed_messages()方法,获取Flask路由传来的闪现信息

{% for msg in get_flashed_messages() %}
    <p> {{ msg }} </p>
{% endfor %}

这种闪现信息是从Flask路由中传来的,只要在路由中发一个flash('hello')信息,相当于弹了一个alert()。然后我们可以在Jinja2的模版中用get_flashed_messages()获得flash过来的信息列表。


Solomon's 技术专栏
主要收录自己的一些技术文章
1 篇内容引用

Those who exalt themselves will be humbled, and those who humble themselves will be exalted.

1.2k 声望
475 粉丝
0 条评论
推荐阅读
Mac上的gdb之:从入门到放弃
副标题:Mac上的gdb无法正常调试的问题 Mac上用brew install gdb安装gdb后,无法正常的运行run命令,报错如下: {代码...} 这个不是c程序的问题,也不是gdb的问题,而是Mac的问题。 参考:gdb doesn't work on ma...

SolomonXie6阅读 10.4k

2023 新年好(顺便记 Flask 的 Bad request 错误)
如果你用 Flask 实现过 restful 的接口,可能经常会遇到发送 POST 请求的时候,返回 400 BAD REQUEST 的情况,这时候即使可以调试,也看不到更多的错误信息了,因为还没执行到自己的业务代码呢。这十有八九是因为...

songofhawk阅读 1.4k

封面图
Flink 1.16:Hive SQL 如何平迁到 Flink SQL
摘要:本文整理自 Apache Flink PMC&Committer 伍翀(云邪)在 9 月 24 日 Apache Flink Meetup 的演讲。主要内容包括:Hive SQL 迁移的动机Hive SQL 迁移的挑战Hive SQL 迁移的实践Hive SQL 迁移的演示未来规划

ApacheFlink阅读 1k

封面图
二、Django
Django 提示:本文根据b站黑马python课整理链接指引 =&gt; 黑马程序员python企业级开发项目-手把手从0到1开发《美多商城》MVT图解项目准备1.创建项目 {代码...} 2.创建应用 {代码...} 3.更换python解释器 {代码.....

玲小叮当阅读 951

Mysql到TiDB迁移,双写数据库兜底方案
TiDB 作为开源 NewSQL 数据库的典型代表之一,同样支持 SQL,支持事务 ACID 特性。在通讯协议上,TiDB 选择与 MySQL 完全兼容,并尽可能兼容 MySQL 的语法。因此,基于 MySQL 数据库开发的系统,大多数可以平滑迁...

京东云开发者阅读 849

封面图
自定义数据采集export到prometheus使用 Flask实现
如图 想要取到 url get请求的值,使用prometheus blackbox 无法获取,所以考虑使用flask自定义exporter 获取

台湾省委书记阅读 797

封面图
三、djanjo
Django 提示:本文根据b站黑马python课整理链接指引 =&gt; 黑马程序员python企业级开发项目-手把手从0到1开发《美多商城》视图介绍和项目准备视图介绍视图就是应用中views.py文件中的函数视图的第一个参数必须为H...

玲小叮当阅读 778

Those who exalt themselves will be humbled, and those who humble themselves will be exalted.

1.2k 声望
475 粉丝
宣传栏