简介

对于jinjia2来说,模板仅仅是文本文件,可以生成任何基于文本的文件格式,例如HTML、XML、CSV、LaTex 等等,以下是基础的模板内容:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <ul>
  11. {% for item in seq %} {# test #}
  12. <li>{{ item }}</li>
  13. {% endfor %}
  14. </ul>
  15. </body>
  16. </html>

其中{% %}是用来执行表达式或者赋值,{{ }}则是用来显示对应变量的值,可以是表达式中的值,也可以是应用传入的值,{# #}相当于是python的注释,这个是模板中的注释。除此之外,这些标识符都可以在Environment中进行自定义修改,不过一般不会修改。

变量

众所周知,模板文件中存在表达式和变量,那么变量是怎么来的呢?当然是在调用render渲染模板时传入的,那么变量有哪几种类型呢?

1.普通值

模板文件

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <h1>{{name}}</h1>
  11. <h2>{{gender}}</h2>
  12. </body>
  13. </html>

调用模板文件传递普通值(存在、不存在)以及不传部分值

  1. from jinja2 import Environment, FileSystemLoader
  2. import pathlib
  3. TEMPLATE_PATH = (
  4. pathlib.Path(__file__).parent.joinpath("template_demo").joinpath("templates")
  5. )
  6. env = Environment(loader=FileSystemLoader(TEMPLATE_PATH))
  7. template = env.get_template("template.html")
  8. # 如下两种方式都可以进行传递
  9. # data = template.render(name="tom", age=18)
  10. data = template.render({"name": "tom", "age": 18})
  11. print(data)

结果

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <h1>tom</h1>
  11. <h2></h2>
  12. </body>
  13. </html>

由结果可以看出,当传递一个不存在值或者不传递模板中所需要的值时,默认的值为空

2.字典

模板文件

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <ul>
  11. <li>{{ item.name }}</li>
  12. <li>{{ item.age }}</li>
  13. <li>{{ item['gender'] }}</li>
  14. </ul>
  15. </body>
  16. </html>

调用模板文件传递字典(值存在、不存在)以及不传部分值

  1. from jinja2 import Environment, FileSystemLoader
  2. import pathlib
  3. TEMPLATE_PATH = (
  4. pathlib.Path(__file__).parent.joinpath("template_demo").joinpath("templates")
  5. )
  6. env = Environment(loader=FileSystemLoader(TEMPLATE_PATH))
  7. template = env.get_template("template2.html")
  8. data = template.render(item={"name": "tom", "gender": "man", "city": "nanjing"}, age=18)
  9. print(data)

结果

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <ul>
  11. <li>tom</li>
  12. <li></li>
  13. <li>man</li>
  14. </ul>
  15. </body>
  16. </html>

由结果可以看出,与普通值类似,当传递一个不存在值或者不传递模板中所需要的值时,默认的值为空。

需要注意的是当传入字典时,在模板文件中有两种方式可以接收字典的值,一种是item.attr,另一种是item['attr'],这两种效果是一致的,在官方文档中说明有如下:

  1. Jinja2 item.attr Python 层中做下面的事情:
  2. 检查 item 上是否有一个名为 attr 的属性。
  3. 如果没有,检查 item 中是否有一个 'attr'
  4. 如果没有,返回一个未定义对象。
  5. item['attr'] 的方式相反,只在顺序上有细小差异:
  6. 检查在 item 中是否有一个 'attr' 项。
  7. 如果没有,检查 item 上是否有一个名为 attr 的属性。
  8. 如果没有,返回一个未定义对象。

如果一个对象有同名的项和属性,这很重要。此外,有一个attr()过滤器,它只查找属性。

那么什么情况下会出现同名的项和属性呢,如下

  1. class Person(object):
  2. def __init__(self, name, age, gender) -> None:
  3. self.name = name
  4. self.age = age
  5. self.gender = gender
  6. self.data = {"name": "mike"}
  7. def __getitem__(self, key):
  8. print('__getitem__')
  9. return self.data[key]
  10. def __setitem__(self, key, value):
  11. print('__setitem__')
  12. self.data[key] = value
  13. def __delitem__(self, key):
  14. print('__delitem__')
  15. del self.data[key]
  16. p = Person("tom", "123", "man")
  17. print(p.name)
  18. print(p['name'])
  1. tom
  2. __getitem__
  3. mike

p.namep['name']分别是由不同的内置函数所控制的,p.name是由__setattr __、__getattr __将对应数据从__dict__中添加或者获取,p['name']是由__getitem __、__setitem __、__delitem __将对应数据从自定义字典中添加或获取、删除,只需要保证二者对应的字典中出现重名的即可。

3.序列(列表、集合、元组等)

模板文件

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <ul>
  11. {% for item in seq %}
  12. <li>{{ item }}</li>
  13. {% endfor %}
  14. </ul>
  15. </body>
  16. </html>

调用模板文件传递字典(值存在、不存在)以及不传部分值

  1. from jinja2 import Environment, FileSystemLoader
  2. import pathlib
  3. TEMPLATE_PATH = (
  4. pathlib.Path(__file__).parent.joinpath("template_demo").joinpath("templates")
  5. )
  6. env = Environment(loader=FileSystemLoader(TEMPLATE_PATH))
  7. template = env.get_template("template3.html")
  8. data = template.render(seq=[1, 2, 3, 4], item=[1, 2, 3])
  9. print(data)

结果

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <ul>
  11. <li>1</li>
  12. <li>2</li>
  13. <li>3</li>
  14. <li>4</li>
  15. </ul>
  16. </body>
  17. </html>

由结果可以看出,与上述类似,当传递一个不存在值或者不传递模板中所需要的值时,默认的值为空(如果处于循环中则不显示)。除此之外,序列中元素可以在模板中进行遍历。

4.自定义对象

对象就可以是上述字典中所描述的重名对象,

模板文件如下:

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <ul>
  11. <li>{{ item.name }}</li>
  12. <li>{{ item['name'] }}</li>
  13. <li>{{ item.age }}</li>
  14. <li>{{ item['gender'] }}</li>
  15. </ul>
  16. </body>
  17. </html>

调用模板文件传递对象

  1. p = Person("tom", "123", "man")
  2. print(p.name)
  3. print(p['name'])
  4. TEMPLATE_PATH = (
  5. pathlib.Path(__file__).parent.joinpath("template_demo").joinpath("templates")
  6. )
  7. env = Environment(loader=FileSystemLoader(TEMPLATE_PATH))
  8. template = env.get_template("template4.html")
  9. data = template.render(item=p)
  10. print(data)

结果

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <ul>
  11. <li>tom</li>
  12. <li>mike</li>
  13. <li>123</li>
  14. <li>man</li>
  15. </ul>
  16. </body>
  17. </html>

由结果可见,item.nameitem['name']虽然同名,但是不同值,当然可以使用attr过滤器只查询属性,只需要将变量改为如下方式,就只会获取到属性,详细用法到下面过滤器再进行说明。

  1. <li>{{ item|attr("name")}}</li>

过滤器

顾名思义,就是对传入模板的变量进行过滤得到符合要求的信息,过滤器的基本用法如下

  1. item|过滤器(参数)
  2. 例如获取对象的属性:
  3. item|attr("name")

除此之外,过滤器还支持多条件过滤,每一次过滤后的结果作为下一个过滤器的参数,例如

  1. 将值进行绝对值后再转变成浮点型
  2. {{ item.sale|abs|float}}

内置过滤器如下:

过滤器名称 过滤器的作用 使用方法
abs(number) 返回number的绝对值 item|abs
attr(obj, name) 获取obj的name属性,类似于obj.name foo|attr("bar")
batch(value, linecount, fill_with=None) 批处理value的过滤器,value必须为可迭代对象(字典、字符串、列表、字典等),根据linecount将value分成多个linecount个数的块,不够的使用fill_with的参数补全,返回的是一个生成器。 item|batch(2, '&nbsp;')
capitalize(s) 将字符串s首字母大写 item|capitalize
center(value, width=80) 将value值在width字符中居中, 默认width为80 item|center(20)
default(value, default_value=u'', boolean=False) 当value未传值时显示default_value默认值,需要注意当value为空字符串时,default_value将不会显示,需将boolean设置为true才会显示 item|default("test")
dictsort(value, case_sensitive=False, by='key') 将value字典按照键值对的形式形成元组并排序添加到列表中,类似于[('age', 10), ('name', 20)],case_sensitive:排序时是否区分大小写,by:排序的依据,默认为key item|dictsort(true)
escape(s) 将特殊字符( &, <, >, ‘, ”)转换成安全的html,就是转义 item|escape
filesizeformat(value, binary=False) 将文件格式化成人类可读的文件大小,默认十进制,binary为true时使用二进制 item\filesizeformat
first(seq) 返回序列的第一个元素 item|first
float(value, default=0.0) 将value转为浮点类型,默认为0.0 ite|float
forceescape(value) 强制value html转义 item|forceescape
format(value, *args, **kwargs) 格式化字符串 {{ "%s - %s"|format("Hello?", "Foo!") }} Hello? - Foo!
  • batch(value, linecount, fill_with=None)详解

    当前存在如下模板文件
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <table>
  11. {{item}}
  12. {{item|batch(2, '&nbsp;')|list}}
  13. {%- for row in item|batch(2, '&nbsp;') %}
  14. <tr>
  15. {%- for column in row %}
  16. <td>{{ column }}</td>
  17. {%- endfor %}
  18. </tr>
  19. {%- endfor %}
  20. </table>
  21. </body>
  22. </html>

python代码

  1. from jinja2 import Environment, FileSystemLoader
  2. import pathlib
  3. TEMPLATE_PATH = (
  4. pathlib.Path(__file__).parent.joinpath("template_demo").joinpath("templates")
  5. )
  6. env = Environment(loader=FileSystemLoader(TEMPLATE_PATH))
  7. template = env.get_template("template5.html")
  8. data = template.render(item="asdadsa")
  9. print(data)

结果

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. <table>
  11. asdadsa
  12. [['a', 's'], ['d', 'a'], ['d', 's'], ['a', '&nbsp;']]
  13. <tr>
  14. <td>a</td>
  15. <td>s</td>
  16. </tr>
  17. <tr>
  18. <td>d</td>
  19. <td>a</td>
  20. </tr>
  21. <tr>
  22. <td>d</td>
  23. <td>s</td>
  24. </tr>
  25. <tr>
  26. <td>a</td>
  27. <td>&nbsp;</td>
  28. </tr>
  29. </table>
  30. </body>
  31. </html>

由结果可以看见,将传入的asdadsa变为了[['a', 's'], ['d', 'a'], ['d', 's'], ['a', '&nbsp;']],item|batch(2, '&nbsp;')将传入值按照每两个一组的形式,缺少的使用 补充,由此形成了一个内部嵌套可迭代对象的生成器,需要使用两次for循环获取数据,此处是因为使用了list转变成了列表。这方法非常适用于数据中存在分段数据格式需要统一(例如表格中的数据,可以传入所有数据,分块自动显示数据)。

测试

测试主要是测试一个变量或者一个表达式,使用is

注释

在模板中使用注释,需要注意,原有的模板文件的格式注释不适用,需要使用{# #},也可以自定义注释的风格,使用Environment中的comment_start_stringcomment_end_string进行修改,注意需要首尾呼应。

空白控制

默认情况下,模板引擎不会对模板中的空白做任何修改,如果应用配置了Environment的 trim_blocks ,模板标签后的第一个换行符会被自动移除。

此外,也支持手动将空白删除,只需在需要的块前或者块后添加-即可,例如,清除了for之前的空白及属性后的空白,需要注意的是标签-之间不能留空白。

  1. {%- for i in item %}
  2. {{i}}
  3. {%- endfor %}

转义

当希望Jinjia2忽略某些变量或者块、标签时,尤其是内置的标签,例如当你需要显示{{,使用{{ {{ }}会报错,需要使用{{ '{{' }}

如果对于较大的块的话,例如想在网页展示jinjia2的语法,如下,使用{% raw %}{% endraw %}包裹即可。

  1. {% raw %}
  2. <ul>
  3. {% for item in seq %}
  4. <li>{{ item }}</li>
  5. {% endfor %}
  6. </ul>
  7. {% endraw %}

行语句

使用Enviromentblock_start_stringblock_end_string设置行语句前缀为#时,默认会清除行首的空白,如下两种方式是一致的, 需要注意的是当启用行语句后,除了#后面的逻辑操作之外,不建议在同一行进行其他操作。

  1. <ul>
  2. # for item in seq
  3. <li>{{ item }}</li>
  4. # endfor
  5. </ul>
  6. <ul>
  7. {% for item in seq %}
  8. <li>{{ item }}</li>
  9. {% endfor %}
  10. </ul>

若有未闭合的圆括号、花括号或方括号,行语句可以跨越多行:

  1. <ul>
  2. # for href, caption in [('index.html', 'Index'),
  3. ('about.html', 'About')]:
  4. <li><a href="{{ href }}">{{ caption }}</a></li>
  5. # endfor
  6. </ul>

除了行语句之外还有行注释,使用Environment中的comment_start_stringcomment_end_string修改即可设置行注释, 例如修改为#, #之后的都将作为注释。

python jinjia2 使用语法的更多相关文章

  1. python yield from 语法

    python yield from 语法 yield语法比较简单, 教程也很多 , yield from的中文讲解很少 , python官网是这样解释的 PEP 380 adds the yield ...

  2. Python基础:语法基础(3)

    本篇主要介绍Python中一些基础语法,其中包括:标识符.关键字.常量.变量.表达式.语句.注释.模块和包等内容. 1. 标识符和关键字 1.1 标识符 标识符是变量.常量.函数.属性.类.模块和包等 ...

  3. Python的基础语法(二)

    0. 前言 接着上一篇博客的内容,我将继续介绍Python相关的语法.部分篇章可能不只是简单的语法,但是对初学者很有帮助,也建议读懂. 1. 表达式 由数字.符号.括号.变量等组成的组合. 算术表达式 ...

  4. 六. Python基础(6)--语法

    六. Python基础(6)--语法 1 ● Python3中, Unicode转字节的方法 print(bytes("李泉", encoding = 'utf-8')) prin ...

  5. 五. Python基础(5)--语法

    五. Python基础(5)--语法 1 ● break结束的是它所在的循环体, continue是让它所在的循环体继续循环 # 打印: 1 10 2 10 3 10 4 10 5 10 6 10 7 ...

  6. 四. Python基础(4)--语法

    四. Python基础(4)--语法 1 ● 比较几种实现循环的代码 i = 1 sum = 0 while i <= 10: # 循环10-1+1=10次     sum += i     i ...

  7. 三. Python基础(3)--语法

    三. Python基础(3)--语法 1. 字符串格式化的知识补充 tpl = "我是%s,年龄%d,学习进度100%" %('Arroz',18) print(tpl) # 会提 ...

  8. 二. Python基础(2)--语法

    二. Python基础(2)--语法 1.实现一个简单的登录系统 '''# 形式1 n = 1 while n < 4:     name = input("请输入姓名\n" ...

  9. 一. Python基础(1)--语法

    一. Python基础(1)--语法 1. 应用程序 1.1 什么是计算机(Computer)? 组成 ①运算器 arithmetic unit; ※ Arithmetic unit and cont ...

随机推荐

  1. typescript 的安装和检测是否安装成功

    全局安装typescript npm install -g typescript 检查typescript是否安装成功 tsc -v

  2. 负载均衡之LVS的三种模式

    模式一:D-NAT模式 原理:此模式类似NAT网络中,所以此网络内主机发到互联网上的数据包的源目的IP都是NAT路由的IP,在NAT路由上做了IP替换. 把客户端发来的数据的IP头的目的地址在负载均衡 ...

  3. 对比不同版本windows对libreoffice的支持情况

    由于最近需要用到libreoffice进行对文档转换为pdf,不光需要考虑在linux下的表现,还需要对比下Windows下的兼容性. 在网上各个论坛都找了下,以及libreoffice的中文社区发帖 ...

  4. MVC 调试页面路径变成 Views/Controller/Action.cshtml问题

    MVC在路由里面已经写好了路径,但是调试时地址栏还是会变成 Views/Controller/Action.cshtml,导致报404错误,找不到路径. 原因可能是你将某一页面设为了起始页,导致每次运 ...

  5. 【雅礼集训 2017 Day2】棋盘游戏

    loj 6033 description 给一个\(n*m\)的棋盘,'.'为可通行,'#'为障碍.Alice选择一个起始点,Bob先手从该点往四个方向走一步,Alice再走,不能走走过的点,谁不能动 ...

  6. Java的标识符与关键字

    目录 Java关键字 总表:java关键字共53个(其中包含两个保留字const,goto) Java标识符 定义 组成 命名规则 视频课程 Java关键字 Java关键字是电脑语言里事先定义的,有特 ...

  7. (数据科学学习手札137)orjson:Python中最好用的json库

    本文示例代码及文件已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 大家好我是费老师,我们在日常使用Pytho ...

  8. Dubbo的基本使用

    Dubbo分为提供者和消费方  并且两者都要注册到ZK上 提供者 注解    @Service   这是dubbo包下的 消费组 注解    @Reference 远程注入 第一步导入依赖 <! ...

  9. springboot available: expected at least 1 bean which qualifies as autowire candidate奇葩问题

    Exception encountered during context initialization - cancelling refresh attempt: org.springframewor ...

  10. MAUI与Blazor共享一套UI,媲美Flutter,实现Windows、macOS、Android、iOS、Web通用UI

    1. 前言 距离上次发<MAUI初体验:爽>一文已经过去2个月了,本计划是下半年或者明年再研究MAUI的,现在计划提前啦,因为我觉得MAUI Blazor挺有意思的:在Android.iO ...