美文网首页
Python模板引擎Jinja2(二)

Python模板引擎Jinja2(二)

作者: 狄仁杰666 | 来源:发表于2021-01-09 23:45 被阅读0次

前言

来啦老铁!

今天咱们继续一起来学习Python模板引擎Jinja2的另外2个重要知识点:

  • 宏;

  • 模板继承;

代码已更新至仓库,自行取阅:

1. 宏;

简单的说,宏与代码中方法的封装、前端组件的概念类似,即我们对Jinja2模板中经常使用的页面元素(当然,也可以是复杂的页面片段)进行封装,这样可以方便代码复用,降低代码冗余。同时,支持有入参的宏。

还不够清楚?咱们来实践实践!宏的编写有2种方式:

  • 一种是在模板中直接进行封装;

  • 一种是将代码块封装到独立的宏文件中去;

(可以参考一下我们平时怎么封装方法、函数的)

1). 在模板中直接进行封装:

  • 在模板文件夹中新增jinja2_maro_demo_1.html,织入如下模板代码:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{% macro input(id, type='text', value='') %}
<input type="{{ type }}" id="{{ id }}" value="{{ value|e }}">
{% endmacro %}

Username:<p>{{ input('username',value=user_name) }}</p>
Password:<p>{{ input('password', type='password',value=pass_word) }}</p>
</body>
</html>

  • 这个东西就是宏:
{% macro input(id, type='text', value='') %}
<input type="{{ type }}" id="{{ id }}" value="{{ value|e }}">
{% endmacro %}

这里将一个input框抽成一个宏,入参id,type(带有默认值text),value分别为input html元素的3种属性,这样我们可以根据传递给宏的参数,渲染出含有不同属性的input框,如普通input框,密码input框等。

  • 而这个就是使用宏的示例:

(其中user_name和pass_word是模板的外部入参,由渲染逻辑传入)

Username:<p>{{ input('username',value=user_name) }}</p>
Password:<p>{{ input('password', type='password',value=pass_word) }}</p>
  • 最后写一个渲染逻辑:

(我们给模板传一个user_name为dylanz、pass_word为123的参数)

def create_jinja2_macro_demo_1_html(self):
    env = Environment(loader=PackageLoader('resources', 'templates'))
    template_name = 'jinja2_macro_demo_1.html'
    template = env.get_template(template_name)
    html = template.render(user_name='dylanz', pass_word='123')

    self.write_output_html(template_name, html)
  • 执行渲染逻辑;
  • 渲染完成后,浏览器打开output文件夹下新生成的jinja2_macro_demo_1.html文件
宏示例1
这样我们就完成了一个带入参的宏,被渲染出多个页面元素的示例啦!

不带入参的宏更简单,把参数去掉就好了,如:

{% macro input() %}
<input type="text" id="test" value="">
{% endmacro %}

2). 将代码块封装到独立的宏文件中去;

承接上面的例子,我们将宏写到独立的文件中去,然后在模板文件中引入,最后完成渲染。

  • 新建宏文件;

在模板文件下新建宏文件夹macros文件夹,在文件夹新建宏文件,如:macro_demo.html,在文件中织入宏代码(就是将宏代码搬到macro_demo.html而已):

{% macro input(id, type='text', value='') %}
<input type="{{ type }}" id="{{ id }}" value="{{ value|e }}">
{% endmacro %}
  • 新的模板文件;

新建模板文件jinja2_macro_demo_2.html,织入代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{% from 'macros/macro_demo.html' import input %}

Username:<p>{{ input('username',value=user_name) }}</p>
Password:<p>{{ input('password', type='password',value=pass_word) }}</p>
</body>
</html>
这里关键的一行代码,将宏引入模板文件:
{% from 'macros/macro_demo.html' import input %}
  • 配套的渲染逻辑:
def create_jinja2_macro_demo_2_html(self):
    env = Environment(loader=PackageLoader('resources', 'templates'))
    template_name = 'jinja2_macro_demo_2.html'
    template = env.get_template(template_name)
    html = template.render(user_name='dylanz', pass_word='123')

    self.write_output_html(template_name, html)
  • 执行渲染逻辑;
  • 渲染完成后,浏览器打开output文件夹下新生成的jinja2_macro_demo_2.html文件:
宏示例2

效果跟直接在模板中声明宏、引用宏一样,说明将代码块封装到独立的宏文件中去,然后再在模板中引用的示例正确无误

这里有几个注意点:

a. 宏文件必须在模板文件夹下或模板文件夹下任意文件夹,因此我们是在templates下新建的macros文件夹;

b. 引入宏的方式,不仅只有{% from 'macros/macro_demo.html' import input %} 这种方式,其实import语句的用法跟python中的import类似,可以直接import...as...,也可以from...import...或者from...import...as...;

c. 宏文件中也可以引用其它宏,使用include关键字代码,如:

{% include 'other_macro_1.html' %}
自己的宏代码
{% include 'other_macro_2.html' %}

2. 模板继承;

模板的继承同样提高了模板代码的重复利用性,我们在父模板中预留位置(称之为block),子模板继承后,再对预留的位置进行实现,这样既保留父模板的通用部分,又能对某些模板位置进行定制。

废话不多说,咱直接开整!

我们在templates文件夹下建立2个模板文件parent.html和child.html:
  • parent.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

<div>这被继承的父模板</div>
{% block content %}
<div>这里是预留位置</div>
{% endblock %}

</body>
</html>

其中,这个就是父模板中为字模板预留的位置,<div>这里是预留位置</div>是我们自己随便放的用于标记一下,真实场景中也可以放任意html:

{% block content %}
<div>这里是预留位置</div>
{% endblock %}

(注意:content为block名字,可任意取)

  • child.html:
{% extends "parent.html" %}
{% block content %}
{{ super() }}
<p>
Hi,这是子模板定制的内容
</p>
{% endblock %}
  • 渲染逻辑:
def create_child_html(self):
    env = Environment(loader=PackageLoader('resources', 'templates'))
    template_name = 'child.html'
    template = env.get_template(template_name)
    html = template.render()

    self.write_output_html(template_name, html)
  • 执行渲染逻辑:

展示前介绍几个注意点:

a. 子模板就不用再写完整的模板文件了;

子模板直接继承parent.html,然后往父模板预留的位置写入内容,如本例为:Hi,这是子模板定制的内容

{% block content %}
{{ super() }}
<p>
Hi,这是子模板定制的内容
</p>
{% endblock %}

b. 当使用了{{ super() }},则父模板预留位置内的内容会保留,即<div>这里是预留位置</div>这个会保留:

继承示例1:有{{ super() }}

c. 当未使用{{ super() }},则则父模板预留位置内的内容不保留,即<div>这里是预留位置</div>这个会去除:

继承示例2:无{{ super() }}

d. 如果父模板中,想使用预留位置的内容,则可以像这样,在父模板中添加代码:

<div>
父模板中再次使用预留位置的内容:
{{self.content()}}
</div>
继承示例3:父模板使用预留位置的内容
至此,我们学习实践了Jinja2的2个重要概念,Jinja2学到这里基本就告一段落了,剩下的就交给时间,交给具体使用场景的考验了!

整个不会很难,建议跟着文章动手做,很容易就能理解。

当然笔者也是参考网上的一些文章,如有不足或错误,烦请指正,感谢!

如果本文对您有帮助,麻烦动动手指点点赞?

谢谢!

相关文章

网友评论

      本文标题:Python模板引擎Jinja2(二)

      本文链接:https://www.haomeiwen.com/subject/agrhaktx.html