美文网首页
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