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

Python模板引擎Jinja2(一)

作者: 狄仁杰666 | 来源:发表于2021-01-03 22:32 被阅读0次

    前言

    来啦老铁!

    笔者近期在工作中遇到将测试数据可视化的需求,且在Python语言背景下,当时借用的是团队既有经验,即:

    • 模板引擎技术

    而模板引擎使用:Jinja2

    看过笔者的Spring Boot全家桶系列文章的同学一定不会陌生,我们曾在文章Spring Boot视图技术中,一起学习了java体系下的视图技术(模板引擎技术),咱们今天也来学习学习Python体系下的模板引擎技术吧!

    学习路径

    1. 常见的Python模板引擎有哪些?
    2. Jinja2简介;
    3. Jinja2入门使用;
    4. Jinja2的基础知识点;

    1. 常见的Python模板引擎有哪些?

    首先我们来看看网上的大佬们都玩过哪些Python的模板引擎吧:

    • pyTemplate
    • pyTenjin
    • Tornado.template
    • PyJade
    • Genshi
    • Django
    • Smarty
    • Mako
    • Jinja2
    • 等。

    这么多?笔者只听过Django和Jinja2,孤陋寡闻了,有兴趣的朋友请移步百度~

    2. Jinja2简介;

    来源:https://www.cnblogs.com/yanjiayi098-001/p/11701150.html

    1). Jinja2介绍:

    jinja2是Flask作者开发的一个模板系统,起初是仿django模板的一个模板引擎,为Flask提供模板支持,由于其灵活,快速和安全等优点被广泛使用。

    2). Jinja2的优点:
    • 相对于Template,jinja2更加灵活,它提供了控制结构,表达式和继承等;
    • 相对于Mako,jinja2仅有控制结构,不允许在模板中编写太多的业务逻辑;
    • 相对于Django模板,jinja2性能更好;
    • Jinja2模板的可读性很棒。

    3. Jinja2入门使用;

    话不多说,咱直接开整,代码仓库:

    我们直接开始撸一个简单的渲染例子,当然,在使用Jinja2前,需要安装Jinja2哟:

    pip3 install jinja2
    
    1). 创建模板文件;

    模板文件即html文件,我们在项目内创建一个python包,如resources包,在resources包内创建一个模板文件夹templates,用于存放Jinja模板,最后在templates文件夹下创建一模板文件如:jinja2_demo_1.html;

    2). 编写模板文件;

    在jinja2_demo_1.html文件中,编写简单的Jinja模板,代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Jinja2-demo-1</title>
    </head>
    <body>
    <table border="1">
        <thead>
        <tr>
            <th>INDEX</th>
            <th>STATUS</th>
            <th>MESSAGE</th>
            <th>CREATED_WHEN</th>
        </tr>
        </thead>
    
        <tbody>
        <tr>
            <td>{{index}}</td>
            <td>{{status}}</td>
            <td>{{message}}</td>
            <td>{{created_when}}</td>
        </tr>
        </tbody>
    </table>
    </body>
    </html>
    

    我们会发现,模板中没有写死的数据,而是以{{}}符号包裹变量,如果这时候直接浏览器打开resources/templates/jinja2_demo_1.html文件,效果为:

    浏览器打开模板文件

    没错,就是个模板而已,没有真实值。接下来我们就来将{{}}符号包裹变量变成我们想展示的值吧!

    3). 创建模板渲染逻辑处理类;

    在项目根目录下创建一个python包,如utils包,在包内创建一个python类,如reportUtil.py,类中编写一简单的模板渲染逻辑,如下:

    #!/usr/local/bin/python3
    # -*- coding:utf-8 -*-
    
    __author__ = "diren"
    __date__ = "2021-01-03 15:50"
    
    import os
    import time
    
    from jinja2 import Environment, PackageLoader
    
    
    class ReportUtil:
        def __init__(self):
            pass
    
        def create_jinja2_demo_1_html(self):
            index = 1
            status = "成功"
            message = "这是一个测试文本"
            created_when = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
            env = Environment(loader=PackageLoader('resources', 'templates'))
            template_name = "jinja2_demo_1.html"
            template = env.get_template(template_name)
            html = template.render(index=index, message=message, created_when=created_when, status=status)
    
            current_dir = os.getcwd()
            output_dir = os.path.join(current_dir, "../resources/output/")
            if not os.path.exists(output_dir):
                os.mkdir(output_dir)
            os.chdir(output_dir)
    
            fo = open(template_name, "w")
            fo.writelines(html)
            fo.close()
            os.chdir(current_dir)
            print(f"create {template_name}:", "完成")
    
    
    if __name__ == "__main__":
        ReportUtil().create_jinja2_demo_1_html()
    
    

    这里稍微讲解一下我们的目的:

    • 我们希望通过reportUtil.py,将一组数据渲染进resources/templates/jinja2_demo_1.html文件中表格的第一行;
    • 渲染的数据为:
    index = 1
    status = "成功"
    message = "这是一个测试文本"
    created_when = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    
    • 渲染后的文件存储于resources/output/jinja2_demo_1.html中,

    渲染预期为一个简单表格;

    4). 项目整体结构;
    项目整体结构
    5). 演示;

    运行reportUtil.py,我们能看到resources包下生成了一个output文件夹,output文件夹下有一个html文件:jinja2_demo_1.html,该文件就是我们在reportUtil.py渲染出来的静态html文件:

    渲染html

    浏览器打开resources/output/jinja2_demo_1.html文件:

    浏览器访问html

    嗯,没错,原来{{}}符号包裹的变量,均变成我们reportUtil.py代码中想渲染的真实值了,渲染演示成功!是不是很简单呀!

    上述,演示了一个非常简单的Jinja2使用方法,接下来我们一起来边学习Jinja2的常用功能,边码代码、边演示、边学习吧!

    4. Jinja2的基础知识点;

    这里罗列一下基础知识点:

    • 基本语法;
    • 运算符;
    • 转义方法;
    • 测试器;
    • 如何在模版页面中引入静态文件?
    • 过滤器;
    • 宏;
    • 模板继承;

    1). 基本语法;

    • 注释 {#...#}
      例如:{#这是一个注释#},这一行代码是不会被渲染、处理的,起注释作用;

    • 变量取值 {{...}}

    如上面的例子, {{}}是占位符,Jinja2渲染时会将这些占位符替换成真实值。它支持python中的所有数据类型,如字符串、字典、列表等。

    • 控制结构 {% ... %}

    该符号包裹的内容表示控制结构,如分支、循环,我们来演示一下:

    (1). if语句:
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Jinja2-demo-1</title>
    </head>
    <body>
    <table border="1">
        <thead>
        <tr>
            <th>INDEX</th>
            <th>STATUS</th>
            <th>MESSAGE</th>
            <th>CREATED_WHEN</th>
        </tr>
        </thead>
    
        {#这是一个注释#}
        <tbody>
        {% if index==1 %}
        <tr>
            <td>{{index}}</td>
            <td>{{status}}</td>
            <td>{{message}}</td>
            <td>{{created_when}}</td>
        </tr>
        {% elif index==2 %}
        <tr>
            <td>{{index}}</td>
            <td>{{status}}</td>
        </tr>
        {% else %}
        <tr>
            <td>{{index}}</td>
            <td>{{status}}</td>
            <td>{{message}}</td>
        </tr>
        {% endif %}
        </tbody>
    </table>
    </body>
    </html>
    

    很简单,当index为1,2,其他值时,表格显示的内容略有差异:

    index为1时 index为2时 index为其他值时
    (2). for语句:

    我们使用for语句,演示渲染一个含有多条数据的表格,并且为了演示效果,我顺便从网上找了个样式,稍作调整,创建新的模板文件jinja2_demo_2.html:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Jinja2-demo-2</title>
    </head>
    <body>
    <title>{{title}}</title>
    <div class="card">
        <div class="card-title">
            <span style="color: #ffffff; font-size: 28px; font-weight: 700">{{title}}</span>
        </div>
        <div class="card-content">
            <div>最终结果:{{ status }}</div>
            <div>发布日期:{{ created_when }}</div>
        </div>
    </div>
    <br>
    
    <table class="pure-table pure-table-bordered">
        <thead>
        <tr>
            <th>INDEX</th>
            <th>STATUS</th>
            <th>MESSAGE</th>
            <th>CREATED_WHEN</th>
        </tr>
        </thead>
    
        <tbody>
        {% for item in details %}
        <tr class="{{ loop.cycle('odd', 'even') }}">
           <td>{{item.index}}</td>
            <td>{{item.status}}</td>
            <td>{{item.message}}</td>
            <td>{{item.created_when}}</td>
        </tr>
        {% endfor %}
        </tbody>
    </table>
    </body>
    </html>
    <style type="text/css">
        .odd {
    
        }
    
        .even {
            background-color: #F5F5F5;
        }
    
        .card-title {
            -moz-border-bottom-colors: none;
            -moz-border-left-colors: none;
            -moz-border-right-colors: none;
            -moz-border-top-colors: none;
            background-color: #B0C4DE;
            border-color: #e7eaec;
            -webkit-border-image: none;
            -o-border-image: none;
            border-image: none;
            border-style: solid solid none;
            border-width: 4px 0 0;
            color: inherit;
            margin-bottom: 0;
            padding: 14px 15px 7px;
            min-height: 48px;
        }
    
        .card-content {
            background-color: #fff;
            color: inherit;
            padding: 15px 20px 20px;
            border-color: #e7eaec;
            -webkit-border-image: none;
            -o-border-image: none;
            border-image: none;
            border-style: solid solid none;
            border-width: 1px 0
        }
    
        .card-content div {
            padding: 6px;
        }
    
        .card {
            box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19);
            text-align: left;
        }
    
        html {
            font-family: sans-serif;
            -ms-text-size-adjust: 100%;
            -webkit-text-size-adjust: 100%;
        }
    
        body {
            margin: 10px;
        }
    
        table {
            border-collapse: collapse;
            border-spacing: 0;
            width: 100%;
            max-width: 100%;
            margin-bottom: 20px;
        }
    
        td,th {
            padding: 0;
        }
    
        .pure-table {
            border-collapse: collapse;
            border-spacing: 0;
            empty-cells: show;
            border: 1px solid #cbcbcb;
        }
    
        .pure-table caption {
            color: #000;
            font: italic 85%/1 arial,sans-serif;
            padding: 1em 0;
            text-align: center;
        }
    
        .pure-table td,.pure-table th {
            border-left: 1px solid #cbcbcb;
            border-width: 0 0 0 1px;
            font-size: inherit;
            margin: 0;
            overflow: visible;
            padding: .5em 1em;
        }
    
        .pure-table thead {
            background-color: #00BFFF;
            color: #000;
            text-align: left;
            vertical-align: bottom;
        }
    
        .pure-table td {
            background-color: transparent;
        }
    
        .pure-table-bordered td {
            border-bottom: 1px solid #cbcbcb;
        }
    
        .pure-table-bordered tbody>tr:last-child>td {
            border-bottom-width: 0;
        }
    </style>
    

    reportUtil.py中也新增一渲染方法create_jinja2_demo_2_report,代码如下:

    #!/usr/local/bin/python3
    # -*- coding:utf-8 -*-
    
    __author__ = "diren"
    __date__ = "2021-01-03 15:50"
    
    import os
    import time
    
    from jinja2 import Environment, PackageLoader
    
    
    class ReportUtil:
        def __init__(self):
            pass
    
        def create_jinja2_demo_1_html(self):
            index = 1
            status = "成功"
            message = "这是一个测试文本"
            created_when = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
            env = Environment(loader=PackageLoader('resources', 'templates'))
            template_name = "jinja2_demo_1.html"
            template = env.get_template(template_name)
            html = template.render(index=index, message=message, created_when=created_when, status=status)
    
            current_dir = os.getcwd()
            output_dir = os.path.join(current_dir, "../resources/output/")
            if not os.path.exists(output_dir):
                os.mkdir(output_dir)
            os.chdir(output_dir)
    
            fo = open(template_name, "w")
            fo.writelines(html)
            fo.close()
            os.chdir(current_dir)
            print(f"create {template_name}:", "完成")
    
        def create_jinja2_demo_2_html(self):
            title = "测试报告"
            status = "失败"
            created_when = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    
            details = [{
                "status": "成功",
                "message": "测试文本1",
                "created_when": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
            }, {
                "index": 2,
                "status": "失败",
                "message": "测试文本2",
                "created_when": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
            }, {
                "index": 3,
                "status": "成功",
                "message": "测试文本2",
                "created_when": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
            }]
    
            env = Environment(loader=PackageLoader('resources', 'templates'))
            template_name = 'jinja2_demo_2.html'
            template = env.get_template(template_name)
            html = template.render(title=title, status=status, created_when=created_when, details=details)
    
            current_dir = os.getcwd()
            output_dir = os.path.join(current_dir, "../resources/output/")
            if not os.path.exists(output_dir):
                os.mkdir(output_dir)
            os.chdir(output_dir)
    
            fo = open(template_name, "w")
            fo.writelines(html)
            fo.close()
            os.chdir(current_dir)
            print(f"create {template_name}:", "完成")
    
    
    if __name__ == "__main__":
        ReportUtil().create_jinja2_demo_1_html()
        ReportUtil().create_jinja2_demo_2_html()
    
    
    运行reportUtil.py后:
    渲染新html for语句渲染效果

    这样,我们顺利将多条数据渲染进模板进行展示,数据为:

            title = "测试报告"
            status = "失败"
            created_when = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    
            details = [{
                "index": 1,
                "status": "成功",
                "message": "测试文本1",
                "created_when": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
            }, {
                "index": 2,
                "status": "失败",
                "message": "测试文本2",
                "created_when": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
            }, {
                "index": 3,
                "status": "成功",
                "message": "测试文本2",
                "created_when": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
            }]
    

    其中表格主题数据为:details;

    我们还可以在循环中加入条件语句,如:
        <tbody>
        {% for item in details %}
        <tr class="{{ loop.cycle('odd', 'even') }}">
            <td>{{item.index}}</td>
            <td>{{item.status}}</td>
            <td>{{item.message}}</td>
            <td>{{item.created_when}}</td>
        </tr>
        {% else %}
        <tr>
            <td>no data found</td>
            <td>no data found</td>
            <td>no data found</td>
            <td>no data found</td>
        </tr>
        {% endfor %}
        </tbody>
    

    则当details为空时,表格会展示一行no data found的数据;

    details为空时
    我们也可以遍历python字典进行展示,如:

    模板:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Jinja2-demo-3</title>
    </head>
    <body>
    <title>{{title}}</title>
    <div class="card">
        <div class="card-title">
            <span style="color: #ffffff; font-size: 28px; font-weight: 700">{{title}}</span>
        </div>
        <div class="card-content">
            <div>最终结果:{{ status }}</div>
            <div>发布日期:{{ created_when }}</div>
        </div>
    </div>
    <br>
    
    <table class="pure-table pure-table-bordered">
        <thead>
        <tr>
            <th>KEY</th>
            <th>VALUE</th>
        </tr>
        </thead>
    
        <tbody>
        {% for key,value in test_dict.items() %}
        <tr class="{{ loop.cycle('odd', 'even') }}">
            <td>{{key}}</td>
            <td>{{value}}</td>
        </tr>
        {% endfor %}
        </tbody>
    </table>
    </body>
    </html>
    <style type="text/css">
        .odd {
    
        }
    
        .even {
            background-color: #F5F5F5;
        }
    
        .card-title {
            -moz-border-bottom-colors: none;
            -moz-border-left-colors: none;
            -moz-border-right-colors: none;
            -moz-border-top-colors: none;
            background-color: #B0C4DE;
            border-color: #e7eaec;
            -webkit-border-image: none;
            -o-border-image: none;
            border-image: none;
            border-style: solid solid none;
            border-width: 4px 0 0;
            color: inherit;
            margin-bottom: 0;
            padding: 14px 15px 7px;
            min-height: 48px;
        }
    
        .card-content {
            background-color: #fff;
            color: inherit;
            padding: 15px 20px 20px;
            border-color: #e7eaec;
            -webkit-border-image: none;
            -o-border-image: none;
            border-image: none;
            border-style: solid solid none;
            border-width: 1px 0
        }
    
        .card-content div {
            padding: 6px;
        }
    
        .card {
            box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19);
            text-align: left;
        }
    
        html {
            font-family: sans-serif;
            -ms-text-size-adjust: 100%;
            -webkit-text-size-adjust: 100%;
        }
    
        body {
            margin: 10px;
        }
    
        table {
            border-collapse: collapse;
            border-spacing: 0;
            width: 100%;
            max-width: 100%;
            margin-bottom: 20px;
        }
    
        td,th {
            padding: 0;
        }
    
        .pure-table {
            border-collapse: collapse;
            border-spacing: 0;
            empty-cells: show;
            border: 1px solid #cbcbcb;
        }
    
        .pure-table caption {
            color: #000;
            font: italic 85%/1 arial,sans-serif;
            padding: 1em 0;
            text-align: center;
        }
    
        .pure-table td,.pure-table th {
            border-left: 1px solid #cbcbcb;
            border-width: 0 0 0 1px;
            font-size: inherit;
            margin: 0;
            overflow: visible;
            padding: .5em 1em;
        }
    
        .pure-table thead {
            background-color: #00BFFF;
            color: #000;
            text-align: left;
            vertical-align: bottom;
        }
    
        .pure-table td {
            background-color: transparent;
        }
    
        .pure-table-bordered td {
            border-bottom: 1px solid #cbcbcb;
        }
    
        .pure-table-bordered tbody>tr:last-child>td {
            border-bottom-width: 0;
        }
    </style>
    

    其中,关键代码:{% for key,value in test_dict.items() %}...{% endfor %}

    reportUtil.py中新增create_jinja2_demo_3_html方法:

    #!/usr/local/bin/python3
    # -*- coding:utf-8 -*-
    
    __author__ = "diren"
    __date__ = "2021-01-03 15:50"
    
    import os
    import time
    
    from jinja2 import Environment, PackageLoader
    
    
    class ReportUtil:
        def __init__(self):
            pass
    
        def create_jinja2_demo_1_html(self):
            index = 1
            status = "成功"
            message = "这是一个测试文本"
            created_when = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
            env = Environment(loader=PackageLoader('resources', 'templates'))
            template_name = "jinja2_demo_1.html"
            template = env.get_template(template_name)
            html = template.render(index=index, message=message, created_when=created_when, status=status)
    
            current_dir = os.getcwd()
            output_dir = os.path.join(current_dir, "../resources/output/")
            if not os.path.exists(output_dir):
                os.mkdir(output_dir)
            os.chdir(output_dir)
    
            fo = open(template_name, "w")
            fo.writelines(html)
            fo.close()
            os.chdir(current_dir)
            print(f"create {template_name}:", "完成")
    
        def create_jinja2_demo_2_html(self):
            title = "测试报告"
            status = "失败"
            created_when = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    
            details = [{
                "status": "成功",
                "message": "测试文本1",
                "created_when": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
            }, {
                "index": 2,
                "status": "失败",
                "message": "测试文本2",
                "created_when": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
            }, {
                "index": 3,
                "status": "成功",
                "message": "测试文本2",
                "created_when": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
            }]
    
            env = Environment(loader=PackageLoader('resources', 'templates'))
            template_name = 'jinja2_demo_2.html'
            template = env.get_template(template_name)
            html = template.render(title=title, status=status, created_when=created_when, details=details)
    
            current_dir = os.getcwd()
            output_dir = os.path.join(current_dir, "../resources/output/")
            if not os.path.exists(output_dir):
                os.mkdir(output_dir)
            os.chdir(output_dir)
    
            fo = open(template_name, "w")
            fo.writelines(html)
            fo.close()
            os.chdir(current_dir)
            print(f"create {template_name}:", "完成")
    
        def create_jinja2_demo_3_html(self):
            title = "人员信息"
            status = "采集成功"
            created_when = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
    
            test_dict = {
                "name": "dylanz",
                "gender": "male",
                "age": 18,
                "professional": "TA"
            }
    
            env = Environment(loader=PackageLoader('resources', 'templates'))
            template_name = 'jinja2_demo_3.html'
            template = env.get_template(template_name)
            html = template.render(title=title, status=status, created_when=created_when, test_dict=test_dict)
    
            current_dir = os.getcwd()
            output_dir = os.path.join(current_dir, "../resources/output/")
            if not os.path.exists(output_dir):
                os.mkdir(output_dir)
            os.chdir(output_dir)
    
            fo = open(template_name, "w")
            fo.writelines(html)
            fo.close()
            os.chdir(current_dir)
            print(f"create {template_name}:", "完成")
    
    
    if __name__ == "__main__":
        ReportUtil().create_jinja2_demo_1_html()
        ReportUtil().create_jinja2_demo_2_html()
        ReportUtil().create_jinja2_demo_3_html()
    
    

    效果:

    遍历字典效果

    Jinja2中for循环内置常量

    细心的同学会发现,在for循环中,我们使用loop.cycle来交替使用单元格样式'odd', 'even',loop.cycle为Jinja2中循环计数内置变量,而Jinja2还拥有其他循环内置常量,有:

    Jinja2中for循环内置常量-来自网络

    篇幅有限,请读者自行了解、尝试哈!

    2). 运算符;

    +号运算符:可以完成数字相加,字符串相加,列表相加。但是并不推荐使用+运算符来操作字符串,字符串相加应该使用~运算符。
    -号运算符:只能针对两个数字相减。
    /号运算符:对两个数进行相除。
    %号运算符:取余运算。
    *号运算符:乘号运算符,并且可以对字符进行相乘。
    **号运算符:次幂运算符,比如2**3=8。
    in操作符:跟python中的in一样使用,比如{{1 in [1,2,3]}}返回true。
    ~号运算符:拼接多个字符串,比如{{"Hello" ~ "World"}}将返回HelloWorld。

    3). 转义方法;

    开启转义:
    在模板渲染字符串的时候,字符串有可能包括一些非常危险的字符比如<、>等,这些字符会破坏掉原来HTML标签的结构,更严重的可能会发生XSS跨域脚本攻击,因此如果碰到<、>这些字符的时候,应该转义成HTML能正确表示这些字符的写法。

    • 对引用的变量值进行转义:{{ 变量名|e }}或{{ 变量名|escape }}
    • 将代码段进行自动转义:{%autoescape true%}...{%endautoescape%},如:
    {% autoescape true %}
    <p>自动转义已开启</p>
    <p>{{ 变量引用值会被自动转义 }}</p>
    {% endautoescape %}
    

    关闭转义:

    • 对引用的变量值关闭转义:{{变量名|safe }}
    • 将代码段关闭自动转义:{%autoescape false%}...{%endautoescape%},如:
    {% autoescape false %}
    <p>自动转义已关闭</p>
    <p>{{ 变量引用值不会被自动转义 }}</p>
    {% endautoescape %}
    
    4). 测试器;

    测试器主要用来判断一个值是否满足某种类型,语法是:if...is...,例如:

    {% if 变量名 is string%}
    字符串变量的值为: {{ 变量名 }}
    {% else %}
    不是字符串变量
    {% endif %}
    

    其中string就是测试器。

    Jinja2中测试器有:

    • callable:是否可调用;
    • defined:是否已经被定义了;
    • escaped:是否已经被转义了;
    • upper:是否全是大写;
    • lower:是否全是小写;
    • string:是否是一个字符串;
    • sequence:是否是一个序列;
    • number:是否是一个数字;
    • odd:是否是奇数;
    • even:是否是偶数;
    5). 如何在模版页面中引入静态文件?

    在Jinja中加载静态文件只需要通过url_for全局函数就可以实现,例如引入static目录下的style.css文件:

    <style type="text/css" href="{{ url_for('static',filename='style.css') }}"/>
    

    该用法需要在Flask框架下,指定静态文件路径方可,此处开卷有益~

    6). 过滤器;

    前面提到的几个用法:{{ 变量名|e }}或{{ 变量名|escape }}、{{变量名|safe }},这些其实是利用了Jinja2中的过滤器功能,过滤器是通过“|”符号进行使用的,符号前为过滤器输入,符号后为过滤器函数、方法、规则,意思是变量值不直接进行渲染,而是根据过滤器函数的规则进行转换后,再进行渲染。

    过滤器函数可将变量值转成绝对值、大小写、转义等再进行渲染,Jinja2拥有许多过滤器规则,我们一起来学习一下吧:
    来源:https://www.cnblogs.com/songyifan427/p/10144506.html

    • abs(value):返回一个数值的绝对值,示例:-1|abs;
    • default(value,default_value,boolean=false):如果当前变量没有值,则会使用参数中的值来代替。示例:name|default('xiaotuo')——如果name不存在,则会使用xiaotuo来替代;boolean=False默认是在只有这个变量为undefined的时候才会使用default中的值,如果想使用python的形式判断是否为false,则可以传递boolean=true。也可以使用or来替换;
    • escape(value)或e:转义字符,会将<、>等符号转义成HTML中的符号。示例:content|escape或content|e;
    • first(value):返回一个序列的第一个元素。示例:names|first;
    • format(value,*arags,**kwargs):格式化字符串。比如:
    {{ "%s" - "%s"|format('Hello?',"Foo!") }}
    将输出:Helloo? - Foo!
    
    • last(value):返回一个序列的最后一个元素。示例:names|last;

    • length(value):返回一个序列或者字典的长度。示例:names|length;

    • join(value,d=u''):将一个序列用d这个参数的值拼接成字符串;

    • safe(value):如果开启了全局转义,那么safe过滤器会将变量关掉转义。示例:content_html|safe;

    • int(value):将值转换为int类型;

    • float(value):将值转换为float类型;

    • lower(value):将字符串转换为小写;

    • upper(value):将字符串转换为小写;

    • replace(value,old,new): 替换将old替换为new的字符串;

    • truncate(value,length=255,killwords=False):截取length长度的字符串;

    • striptags(value):删除字符串中所有的HTML标签,如果出现多个空格,将替换成一个空格;

    • trim:截取字符串前面和后面的空白字符;

    • string(value):将变量转换成字符串;

    • wordcount(s):计算一个长字符串中单词的个数;

    我们可以将过滤器理解为高级版的运算符!

    知识点有点多,再学下去是不是要吐了?
    那我们今天就到此为止吧,下一篇,我们再继续学习Jinja2的另外2个重要概念:

    • 模板继承

    看着就很有食欲啊,敬请期待!

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

    谢谢!

    相关文章

      网友评论

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

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