zoukankan      html  css  js  c++  java
  • Flask 学习(二)jinja2模板介绍

    控制语句和表达式

    举例

    Flask Python代码

    from flask import Flask, render_template, redirect, request
    
    app = Flask(__name__)
    
    STUDENT = {'name': 'Old', 'age': 38, 'gender': ''}
    
    STUDENT_LIST = [
        {'name': 'Old', 'age': 38, 'gender': ''},
        {'name': 'Boy', 'age': 73, 'gender': ''},
        {'name': 'EDU', 'age': 84, 'gender': ''}
    ]
    
    STUDENT_DICT = {
        'a': {'name': 'Old', 'age': 38, 'gender': ''},
        'b': {'name': 'Boy', 'age': 73, 'gender': ''},
        'c': {'name': 'EDU', 'age': 84, 'gender': ''},
    }
    
    @app.route("/detail")
    def detail():
        print(url_for("detail"))
        return render_template("detail.html", **STUDENT)
    
    @app.route("/detail_list", )
    def detail_list():
        return render_template("detail_list.html", stu_list=STUDENT_LIST)
    
    @app.route("/detail_dict")
    def detail_dict():
        return render_template("detail_dict.html", stu_dict=STUDENT_DICT)
    detail.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    
    </head>
    <body>
    {{ stu }}
    <table border="1px">
        <tr>
            <td>name</td>
            <td>age</td>
            <td>gender</td>
        </tr>
        <tr>
            <td>{{ name }}</td>
            <td>{{ age }}</td>
            <td>{{ gender }}</td>
        </tr>
    </table>
    </body>
    </html>
    detail_list.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    
    </head>
    <body>
    {{ stu_list }}
    <table border="1px">
        <tr>
            <td>name</td>
            <td>age</td>
            <td>gender</td>
        </tr>
          {% for stu in stu_list %}
            {% if stu.name != "Old" %}
                {% if stu.age != 73 %}
                    <tr>
                        <td>{{ stu.name }}</td>
                        <td>{{ stu.get("age") }}</td>
                        <td>{{ stu["gender"] }}</td>
                    </tr>
                {% endif %}
            {% endif %}
        {% endfor %}
    </table>
    </body>
    </html>
    detail_dict.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    
    </head>
    <body>
    {{ stu_dict }}
    <table border="1px">
        <tr>
            <td>id</td>
            <td>name</td>
            <td>age</td>
            <td>gender</td>
        </tr>
        {% for stu_key,stu_value in stu_dict.items() %}
            <tr>
                <td>{{ stu_key }}</td>
                <td>{{ stu_value.get("name") }}</td>
                <td>{{ stu_value.age }}</td>
                <td>{{ stu_value.gender }}</td>
            </tr>
        {% endfor %}
    </table>
    </body>
    </html>

    表达式

    1.最常用的是变量,由Flask渲染模板时传过来,比如name
    也可以是任意一种Python基础类型,比如字符串{{stu_list}},用引号括起;或者数值,列表,元祖,字典,布尔值。直接显示基础类型没啥意义,一般配合其他表达式一起用
    2.运算。包括算数运算,如{{ 2 + 3 }};比较运算,如{{ 2 > 1 }};逻辑运算,如{{ False and True }}
    3.过滤器|和测试器is
    4.函数调用,如{{ current_time() }};数组下标操作,如{{ arr[1] }}
    in操作符,如{{ 1 in [1,2,3] }}
    5.字符串连接符~,作用同Python中的+一样,如{{ "Hello " ~ name ~ "!" }}
    6.None值处理{{name or ""}

    控制语句

    Jinja2的控制语句主要就是条件控制语句if,和循环控制语句for,语法类似于Python
    if-else:
    {% if name and name == 'admin'  %}
        <h1>This is admin console</h1>
    {% elif name %}
        <h1>Welcome {{ name }}!</h1>
    {% else %}
        <h1>Please login</h1>
    {% endif %}
    
    for:
      {% for stu in stu_list%}
        {{ stu }}
      {% endfor %}

     过滤器

    字符串

    <body>
    {# 当变量未定义时,显示默认字符串,可以缩写为d #}
    <p>{{ name | default('No name', true) }}</p>
    
    {# 单词首字母大写 #}
    <p>{{ 'hello world' | capitalize }}</p>
    
    {# 单词全小写 #}
    <p>{{ 'XML' | lower }}</p>
    
    {# 去除字符串前后的空白字符 #}
    <p>{{ '  hello  ' | trim }}</p>
    
    {# 字符串反转,返回"olleh" #}
    <p>{{ 'hello' | reverse }}</p>
    
    {# 格式化输出,返回"Number is 99" #}
    <p>{{ '%s is %d' | format("Number", 99) }}</p>
    
    {# 关闭HTML自动转义 #}
    <p>{{ '<em>name</em>' | safe }}</p>
    
    {% autoescape false %}
    {# HTML转义,即使autoescape关了也转义,可以缩写为e #}
    <p>{{ '<em>name</em>' | escape }}</p>
    {% endautoescape %}
    
    </body>

    数值操作

    {# 四舍五入取整,返回13.0 #}
    <p>{{ 12.98 | round }}</p>
    
    {# 向下截取到小数点后2位,返回12.88 #}
    <p>{{ 12.8888 | round(2, 'floor') }}</p>
    
    {# 绝对值,返回12 #}
    <p>{{ -12 | abs }}</p>

    列表操作

    # 取第一个元素 #}
    <p>{{ [1,2,3] | first }}</p>
    
    {# 取最后一个元素 #}
    <p>{{ [1,2,3] | last }}</p>
    
    {# 返回列表长度,可以写为count #}
    <p>{{ [1,2,3,4,5] | length }}</p>
    
    {# 列表求和 #}
    <p>{{ [1,2,3,4,5] | sum }}</p>
    
    {# 列表排序,默认为升序 #}
    <p>{{ [3,2,1,5,4] | sort }}</p>
    
    {# 合并为字符串,返回"1 | 2 | 3 | 4 | 5" #}
    <p>{{ [1,2,3,4,5] | join(' | ') }}</p>
    
    {# 列表中所有元素都全大写。这里可以用upper,lower,但capitalize无效 #}
    <p>{{ ['alex','bob','ada'] | upper }}</p>

    字典

    {% set users=[{'name':'Tom','gender':'M','age':20},
                  {'name':'John','gender':'M','age':18},
                  {'name':'Mary','gender':'F','age':24},
                  {'name':'Bob','gender':'M','age':31},
                  {'name':'Lisa','gender':'F','age':19}]
    %}
    
    
    {# 按指定字段排序,这里设reverse为true使其按降序排 #}
    <ul>
    {% for user in users | sort(attribute='age', reverse=true) %}
         <li>{{ user.name }}, {{ user.age }}</li>
    {% endfor %}
    </ul>
    
    {# 列表分组,每组是一个子列表,组名就是分组项的值 #}
    <ul>
    {% for group in users|groupby('gender') %}
        <li>{{ group.grouper }}<ul>
        {% for user in group.list %}
            <li>{{ user.name }}</li>
        {% endfor %}</ul></li>
    {% endfor %}
    </ul>
    
    {# 取字典中的某一项组成列表,再将其连接起来 #}
    <p>{{ users | map(attribute='name') | join(', ') }}</p>

    自定义过滤器

    # 第一种方式
    def get_even_list(l):
            return l[::2]
    # 函数的第一个参数是过滤器函数,第二个参数是过滤器名称
    app.add_template_filter(get_even_list, 'even_filter')
    
    # 第二种方式
    @app.template_filter()  # 过滤器函数
    def is_even(num):
        if num % 2 == 0:
            return "even number"
        else:
            return "odd number"

    使用

    <p>{{ [1,2,3,4,5] | even_filter }}</p>
    
    <p>{{ 2 | is_even }}</p>

    测试器

    测试器总是返回一个布尔值,它可以用来测试一个变量或者表达式,使用”is”关键字来进行测试。

     {% set name='ab'  %}
    {% if name is lower %}
      <h2>"{{ name }}" are all lower case.</h2>
    {% endif %}

    测试器本质上也是一个函数,它的第一个参数就是待测试的变量,在模板中使用时可以省略去。如果它有第二个参数,

    模板中就必须传进去。测试器函数返回的必须是一个布尔值,这样才可以用来给if语句作判断。

    内置测试器

    举例

    {# 检查变量是否被定义,也可以用undefined检查是否未被定义 #}
    {% if name is defined %}
        <p>Name is: {{ name }}</p>
    {% endif %}
    
    {# 检查是否所有字符都是大写 #}
    {% if name is upper %}
      <h2>"{{ name }}" are all upper case.</h2>
    {% endif %}
    
    {# 检查变量是否为空 #}
    {% if name is none %}
      <h2>Variable is none.</h2>
    {% endif %}
    
    {# 检查变量是否为字符串,也可以用number检查是否为数值 #}
    {% if name is string %}
      <h2>{{ name }} is a string.</h2>
    {% endif %}
    
    {# 检查数值是否是偶数,也可以用odd检查是否为奇数 #}
    {% if 2 is even %}
      <h2>Variable is an even number.</h2>
    {% endif %}
    
    {# 检查变量是否可被迭代循环,也可以用sequence检查是否是序列 #}
    {% if [1,2,3] is iterable %}
      <h2>Variable is iterable.</h2>
    {% endif %}
    
    {# 检查变量是否是字典 #}
    {% if {'name':'test'} is mapping %}
      <h2>Variable is dict.</h2>
    {% endif %}

    官方文档

    https://jinja.palletsprojects.com/en/master/templates/#builtin-tests

    自定义测试器

    定义

    # 自定义测试器
    # 第一种方式
    import re
    def test_tel(tel_num):
        tel_re = r'd{11}'
        return re.match(tel_re,tel_num)
    
    app.add_template_test(test_tel,"is_tel")
    
    # 第二种方式
    @app.template_test('start_with')
    def start_with(str, suffix):
        return str.lower().startswith(suffix.lower())

    使用

    {% set tel = '18910171111' %}
    {% if tel is is_tel %}
      <h2>{{ tel }} is mobile phone</h2>
    {% endif %}
    
    
     {% set name = 'Hello world' %}
    {% if name is start_with 'hello' %}
      <h2>"{{ name }}" start_with "hello"</h2>
    {% endif %}

    全局函数

    内置全局函数

    {# 全局函数range()的作用同Python里的一样,返回指定范围内的数值序列。三个参数分别是开始值,结束值(不包含),间隔。
    如果只传两个参数,那间隔默认为1;如果只传1个参数,那开始值默认为0。 #}
    <ul>
     {% for num in range(10,20,2) %}
      <li>Number is "{{ num }}"</li>
    {% endfor %}
    </ul>
    {# dict()函数,方便生成字典型变量 #}
    
    {% set user = dict(name='Joh',age=22) %}
    <p>{{ user | tojson | safe }}</p>
    
    {# 显示 '{"age": 22, "name": "Joh"}' #}
    
    {# joiner()函数,它可以初始化为一个分隔符,然后第一次调用时返回空字符串,以后再调用则返回分隔符 #}
    {% set sep = joiner("|") %}
    {% for val in range(5) %}
        {{ sep() }} <span>{{ val }}</span>
    {% endfor %}
    {# 显示 "0 | 1 | 2 | 3 | 4" #}
    
    {# cycler()函数,在给定的序列中轮循 #}
    {% set cycle = cycler('odd', 'even') %}
    <ul>
    {% for num in range(10, 20, 2) %}
        <li class="{{ cycle.next() }}">Number is "{{ num }}",
        next line is "{{ cycle.current }}" line.</li>
    {% endfor %}
    {#
    next(),返回当前值,并往下一个值轮循
    reset(),重置为第一个值
    current,当前轮循到的值
    #}
    </ul>

    官方文档

    https://jinja.palletsprojects.com/en/master/templates/#list-of-global-functions

    自定义全局函数

    定义

    # 自定义全局函数
    # 第一种方式
    
    @app.template_global()
    def add_sum(*args):
        return sum(args)
    
    # 第二种方式
    import time
    def current_time(timeFormat="%b %d, %Y - %H:%M:%S"):
        return time.strftime(timeFormat)
    
    app.add_template_global(current_time, 'current_time')

    使用

    <p>{{ add_sum(1,2,3,4,5) }}</p>
    <p>Current Time is: {{ current_time() }}</p>
    <p>Current Day is: {{ current_time("%Y-%m-%d") }}</p>

    块 (Block)

    一般我们的网站虽然页面多,但是很多部分是重用的,比如页首,页脚,导航栏之类的。对于每个页面,都要写这些代码,很麻烦。

    Flask的Jinja2模板支持模板继承功能,省去了这些重复代码。

    template:

    <body>
    你好,template1
    {% block template1 %}
    
    {% endblock %}
    你好,template2
    {% block template2 %}
    
    {% endblock %}
    你好,template
    {% block template %}
    
    {% endblock %}
    </body>

    extend:

    {% extends "he.html" %}
    
    {% block template %}
        <h1>yuan</h1>
    {% endblock %}
    
    {% block template1 %}
        <h1>alex</h1>
    {% endblock %}
    
    {% block template2 %}
        <h1>wu</h1>
        {% include "aaa.html" %}
    {% endblock %}
  • 相关阅读:
    [LeetCode] 304. Range Sum Query 2D
    [LeetCode] 303. Range Sum Query
    [Google] Help employee find the nearest gbike
    Difference between Process and thread?
    Given a family tree, find out if two people are blood related
    [LeetCode] 676. Implement Magic Dictionary 实现神奇字典
    [LeetCode] 659. Split Array into Consecutive Subsequences 将数组分割成连续子序列
    [LeetCode] 815. Bus Routes 公交路线
    [LeetCode] 129. Sum Root to Leaf Numbers 求根到叶节点数字之和
    mybatis example 使用AND 和OR 联合查询
  • 原文地址:https://www.cnblogs.com/xiao-apple36/p/11593099.html
Copyright © 2011-2022 走看看