目录

    • 概览
    • 基本用法
    • 一般用法
    • for 语句的使用
    • if 语句的使用
    • Template Inheritance in Jinja(继承)
    • filter 语句的使用
    • Jinja2 Custom Filters
      • 自定义过滤器示例
    • Macro(宏:相当于函数)
    • 空白行的处理
    • 实际应用
  • 总结

概览

官方文档

Jinja 模板只是一个文本文件,可以 基于模板生成任何基于文本的格式(HTML、XML、CSV、LaTeX 等),一般用在前端的项目中,渲染 HTML 文件。

作为网络工程师,可以将其用来批量生成网络设备的配置。

或者其他需要批量生成文本的场景中。

模板包含变量表达式,这两者在模板求值的时候会被替换为值。模板中还有标签,控制模板的逻辑。模板语法的大量灵感来自于 Django 和 Python 。

基本语法:

  • 语句 {% ... %}
  • 变量 {{ ... }}
  • 注释 {# ... #}

常用的语句包括:for、if、set、include、block、filter 等

变量通过传递字典来进行使用,当使用 for 语句的时候,变量可以是列表。

基本用法

创建和渲染模板的最基本方法是通过 Template,通过创建一个 Template 的实例,
会得到一个新的模板对象,模板对象有一个 render() 的方法,该方法在调用 dictkeywords 参数时填充模板。

from jinja2 import Templatetmpl = Template('hello {{ name}}')
result = tmpl.render(name = '111')
print(result)
# 打印结果
hello 111

一般用法

一般情况下,我们使用 *.j2 文件作为模板文件,用法如下:

# 导入相关模块
from jinja2 import Template, FileSystemLoader, Environment# 首先告诉Jinja2模块,jinja模板文件路径在哪?(如当前目录)
j2_loader = FileSystemLoader('./')# 然后定义一个环境,告诉jinja2,从哪里调用模板
env = Environment(loader=j2_loader)# 之后通过 get_template 获取并载入模板
j2_tmpl = env.get_template('./jinja2.j2')# 最后传入参数,渲染模板
result = j2_tmpl.render(name="xdai")print(result)

模板 jinja2.j2 的内容如下

# cat jinja2.j2
This is a Jinja2 template file created by {{ name }}.

最终打印结果如下,传入的 name 被赋值给了模板文件,并输出了最终结果:

This is a Jinja2 template file created by xdai.

for 语句的使用

现在有如模板文件如下:

# cat jinja2_for.j2
{% for name in names %}
Hello {{ name }}.
{% endfor %}

通过传入一个列表来批量生成最终的结果。

from jinja2 import Template, FileSystemLoader, Environment
j2_loader = FileSystemLoader('./')
env = Environment(loader=j2_loader)
j2_tmpl = env.get_template('./jinja2_for.j2')
# 传入一个列表,对列表里面的人打招呼
names = ['Zhang San', 'Li Si', 'Wang Wu']
result = j2_tmpl.render(names=names)
print(result)

打印结果如下:


Hello Zhang San.Hello Li Si.Hello Wang Wu.

通过 for 循环,批量生成了 Hello。

还可以传入列表,列表的值是一个字典,然后通过 for 和字典的 . 或者 [] 进行取值(和 Python 语法一致),将上面的模板文件改动如下:

# cat jinja2_for_with_dict.j2
{% for person in people %}
My name is {{ person.name }}, and I am {{ person['age'] }} years old.
{% endfor %}

然后,编写代码如下:

from jinja2 import Template, FileSystemLoader, Environment
j2_loader = FileSystemLoader('./')
env = Environment(loader=j2_loader)
j2_tmpl = env.get_template('./jinja2_for_with_dict.j2')
# 传入一个列表,列表里面的人进行自我介绍
people = [{'name':'Zhang San', 'age': 18},{'name':'Li Si', 'age': 20},{'name':'Wang Wu', 'age': 22},
]
result = j2_tmpl.render(names=names)
print(result)

打印结果如下:


My name is Zhang San, and I am 18 years old.My name is Li Si, and I am 20 years old.My name is Wang Wu, and I am 22 years old.

if 语句的使用

if 语句用来判断,当条件成立时,对语句块文件的内容进行渲染,条件判定失败后则跳过该语句块。

将上文中的 for 循环模板进行修改如下,年龄大于 18 的进行自我介绍。

# cat jinja2_if.j2
{% for person in people %}
{% if person.age > 18 %}
My name is {{ person.name }}, and I am {{ person['age'] }} years old.
{% endif %}
{% endfor %}

代码与上面 for 语句的例子中相同,仅修改了加载模板的名字,打印结果如下:

My name is Li Si, and I am 20 years old.My name is Wang Wu, and I am 22 years old.

可以看到,age 小于 18 的,没有输出相应的文字。

Template Inheritance in Jinja(继承)

在为网络设备配置创建更大、功能更多的模板文件时,可以使用模板继承,将模板分解开来。
比如,创建 VLAN、interface 、OSPF 等各自独立的模板,这样灵活性更高,模板继承可以将这些独立的模板文件连接在一起。

使用 include语句可以将一个模板完全插入到另一个模板中:

{% include 'vlans.j2' %}

另一种继承的方法是使用 bolck 语句,子模板引用父模板后,可以指定其中的某些部分,如果子模板中不存在,则使用父模板中的值。父模板也可以将 bolck 留空,子模板直接填充内容。

# 父模板,cat father.j2
This is father template.
{% block test %}This is line can be replaced.
{% endblock %}
This is father template.# 子模板,cat children.j2
{% extends 'father.j2' %}
{% block test %}
This is children template.
{% endblock %}# 渲染结果,block 被替代,其他内容不变。
This is father template.
This is children template.
This is father template.

filter 语句的使用

filter 语句的作用就是对模板数据块的内容进行格式化修改。
例如:大小写转换、统计长度、计算绝对值等等,内置支持的过滤器可参见官网

来看个例子:

# cat jinja2_filter.j2
{% for person in people %}
My name is {{ person.name | upper() }}, and I am {{ person['age'] }} years old.
{% endfor %}

执行代码不再赘述,打印结果如下:


My name is ZHANG SAN, and I am 18 years old.My name is LI SI, and I am 20 years old.My name is WANG WU, and I am 22 years old.

Jinja2 Custom Filters

内置的 filter 可能会不满足自己的需要,这时就需要进行自定义了。
自定义筛选器只是常规 Python 函数,将筛选器的左侧作为第一个参数,并将参数作为额外的参数或关键字参数传递给筛选器。

可以将自己写的函数、导入的模块等更新到环境中,进而在 Jinja2 中使用。

Jinja2 的默认 filter 是一个字典,查看方式:Environment.filters

使用方法:通过更新 environment 中的 filters 字典,在模板环境中注册。

env = Environment(loader=FileSystemLoader('./templates/'))
env.filters['datetimeformat'] = datetimeformat

在模板中使用:

{{ article.pub_date|datetimeformat }}
# 传参方法
# {{ 42| myfilter(23) }} ==  myfilter(42, 23)

自定义过滤器示例

ipaddress.IPv4Interface 作为过滤器,来实现将传入的 IP 地址变量进行分析。

# 按照jinja2自定义过滤器传参方法定义一个函数,获取其他模块的属性 **getattr**
def custom_ipaddr(ipaddress,operation):from ipaddress import IPv4Interfaceipadd = IPv4Interface(ipaddress)attr = getattr(ipadd,operation)return attr
# 添加到环境中
env = Environment(loader=FileSystemLoader('./roles/cmw7/templates/'))
env.filters['custom_ipaddr'] = custom_ipaddr
# 在模板中使用
# cat filter_test.j2
{{ 192.168.1.1/24 | custom_ipaddr('netmask') }}

Macro(宏:相当于函数)

可以自己编写一个函数,然后在模板中调用

# cat test.j2
{% macro testfunc() %}test string
{% endmacro %}

空白行的处理

通过上面的实践,你可能会发现,生成的结果中,有很多空行,默认情况下,jinja2 会给渲染后的结果加上空行。

如果需要去除模板中的空白,如 For 语句前后、变量表达式的开头或结尾添加减号 (-),就会删除这个语句块之前或之后的空格。

以上文中的 for 循环为例,修改模板如下:

# cat jinja2.j2
{% for name in names -%}
Hello {{ name }}.
{%- endfor %}

注意上面的 - 符号,放在 for 的结尾,是删除语句块之前的空行,放在 endfor 之前,是删除语句块之后的空行,如果前后的空行都删除了,则内容会在同一行,所以,上面模板渲染之后的输出为:

Hello Zhang San.Hello Li Si.Hello Wang Wu.

具体请根据自己的需求来进行空白行的控制。

实际应用

实际应用过程中,由于 jinja2 的模板需要传入字典、列表等,为了方便维护,我们可以使用单独的变量文件来存储这些东西,例如 YAML、JSON 等,一般使用 YAML ,因为简洁易读。

下面通过一个生成交换机配置的文件,来对 jinja2 模板语法进行综合使用。
模板文件如下:

# cat l2_interface.j2
{% for iface in l2_interface -%}
#
interface {{ iface.iface_name }}{% if iface.desc != None -%}description {{ iface.desc }}{% endif -%}
{% if iface.link_type == 'trunk' -%}port link-type trunkundo port trunk permit vlan 1port trunk permit vlan {{ iface.allow_vlan }}
{% else -%}port link-type accessport access vlan {{ iface.allow_vlan }}
{% endif -%}
{% endfor %}

变量文件如下:

---
# l2_interface.yaml
l2_interface:- iface_name: g1/0/1desc: jinja2_render_configlink_type: accessallow_vlan: 10- iface_name: g1/0/2desc: link_type: trunkallow_vlan: 10 20 30

代码如下:

import yaml
from jinja2 import Template, FileSystemLoader, Environmentj2_loader = FileSystemLoader('./')
env = Environment(loader=j2_loader)
j2_tmpl = env.get_template('./l2_interfaces.j2')
# 加载变量文件,解析成列表/字典
with open('l2_interfaces.yaml') as f:vars = yaml.safe_load(f.read())
result = j2_tmpl.render(vars)
print(result)

最终生成了以下配置文件:

#
interface g1/0/1description jinja2_render_configport link-type accessport access vlan 10
#
interface g1/0/2port link-type trunkundo port trunk permit vlan 1port trunk permit vlan 10 20 30

下面是一个我自己写的案例,供参考。
Ansible Role:根据 Jinja2 生成 H3C Comware V7 配置

总结

在实际场景中,可以将固化配置做成模板文件,生成配置时,只要传入指定的参数,就可生成对应的配置,降低配置编写复杂度的同时,也降低了出错的概率。

Jinja2 入门教程、基本概念、简单使用及使用 Jinja2 生成 H3C 交换机配置举例相关推荐

  1. ROS2入门教程—创建一个简单的订阅者和发布者(C++版)

    ROS2入门教程-创建一个简单的订阅者和发布者(C++版) 1 创建功能包 2 创建发布者节点 3 设置发布者节点依赖项 4 设置发布者节点编译规则 5 创建订阅者 6 编译并运行   节点是通过RO ...

  2. 【前端实例代码】Html5+css3+JavaScript创建在线播放架子鼓电子鼓演奏网页效果!前端开发网页设计基础入门教程!超简单~

    b站视频演示效果: [前端实例代码]Html5+css3+JavaScript创建在线播放架子鼓电子鼓演奏网页效果!前端开发网页设计基础入门教程!超简单~ 效果图: 完整代码: <!DOCTYP ...

  3. ROS 入门教程 —— 小海龟简单控制

    ROS 入门教程 -- 小海龟简单控制 这里我们直接介绍命令使用方法,原理请查看我的另外几篇博客: ROS 命令行工具的使用 ROS 创建工作空间与功能包 运行并控制小海龟 由于小海龟并不是 ROS ...

  4. h3c交换机配置远程管理_H3C交换机配置本地登录和远程登录的用户名和密码教程...

    你还在为不知道H3C交换机配置本地登录和远程登录的用户名和密码教程而不知所措么?下面来是学习啦小编为大家收集的H3C交换机配置本地登录和远程登录的用户名和密码教程,欢迎大家阅读: H3C交换机配置本地 ...

  5. python 华为交换机自动配置_Python+YAML+Jinja2批量生成华为交换机配置

    一.YAML简介 YAML是一种简洁的非标记语言,通过空白.缩进.分行组织数据,从而使数据表达清晰易懂. YAML文件,其实就是后缀名为yaml或yml的文本文件. 文件以三道杠表示开头 --- #这 ...

  6. Python爬虫入门教程:超级简单的Python爬虫教程

    这是一篇详细介绍 [Python]爬虫入门的教程,从实战出发,适合初学者.读者只需在阅读过程紧跟文章思路,理清相应的实现代码,30 分钟即可学会编写简单的 Python 爬虫. 这篇 Python 爬 ...

  7. 非常好的Ansible入门教程(超简单)

    文章目录 1 安装 1.1 Ubuntu 2 配置 2.1 管理服务器:Inventory文件 2.2 基础:运行命令 2.2.1 模块(Modules) 模块是使用Ansible 的方法 2.3 剧 ...

  8. 区块链入门教程(10)--开发简单银行合约

    文章目录 1. 任务背景 2. 目标 3. 相关知识点 4. 任务实操 4.1 存储设计 4.2 接口设计 4.3 编写合约 5. 小结 1. 任务背景 开发一个简单银行合约,支持: 开户 转账 查询 ...

  9. 【前端实例代码】Html5+css3创建新拟态新拟物风格(Neumorphism)动画特效图标网页效果!前端开发网页设计基础入门教程!超简单~

    b站视频演示效果: [web前端特效源码]Html5+css3实现新拟态新拟物风格(Neumorphism)网页图标动画效果!手把手教学!新手必会!超简单 ~ 效果图: 完整代码: <!DOCT ...

  10. 关于flask入门教程-ajax+echarts简单实现一

    ECharts是一款基于JavaScript的数据可视化图表库,提供直观,生动,可交互,可个性化定制的数据可视化图表. 本文通过echarts官网上的一个标准样例开始flask+ajax+echart ...

最新文章

  1. 双11大考 POLARDB分钟级弹性让企业轻松扩展
  2. 分布式任务队列 Celery — 应用基础
  3. datatable 查询_2020年浙江注册会计师成绩查询预告
  4. [Err] 1093 - You can't specify target table 's' for update in FROM clause
  5. 关于nagios监控系统添加主机和服务脚本
  6. Unity下载安装教程
  7. 整理了个软件需求规格说明书模板
  8. CUDA组件 -- nvidia driver驱动与toolkit
  9. oracle数据库修改密码方法,修改oracle数据库用户名及密码的方法
  10. 【JS逆向破解】爬虫抓取哦oh漫画实例Java/Python实现
  11. ZStack基本工作原理
  12. android自定义抽屉布局,自定义Drawer,抽屉布局
  13. 2014在线旅游业发展的几大趋势
  14. mark一下江南一点雨的微人事开源项目
  15. 免费安装office流程(官方自动批量激活)
  16. Verilog HDL可综合描述(高质量Verilog书写)
  17. js的slice,splice,split的使用
  18. numpy计算移动平均值
  19. 大数据后从此再无隐私_大数据时代没有个人隐私?
  20. 联想m2600c微型计算机,联想ThinkCentre M2600c瘦客户机:简单性能介绍

热门文章

  1. [量化学院]基于协整的配对交易
  2. 弹出启动windows安全中心服务器,无法启动Windows安全中心服务怎样处理
  3. 傅里叶分析之掐死教程
  4. wps空白页怎么删除,迅速帮你解决问题
  5. 聚合支付系统如何开发?
  6. 儿童python编程入门软件_一款儿童编程入门的理想工具——PythonTurtle
  7. 帝国cms模板html文件夹,帝国cms的模板保存在哪里
  8. 如何在一个月内高效地备考教师资格证?
  9. 在线IDE的原理及设计思路 以Java为例
  10. 像计算机科学家一样思考(C++)