Flask07 Jinja2模板测试器、控制语句IF/FOR、变量/块 赋值、作用域、块级作用域

1 测试器及其使用

  在模板中的 {{}} 可以书写测试器,格式如下

    {{ 变量 is 测试器名称  }}

  1.1 在python中导入 Jinja2 的模板

    from jinja2 import tests

      注意:其实这一步是不需要的,导入的目的是为了查看那些测试器的源代码

# -*- coding: utf-8 -*-
"""
    jinja2.tests
    ~~~~~~~~~~~~

    Jinja test functions. Used with the "is" operator.

    :copyright: (c) 2017 by the Jinja Team.
    :license: BSD, see LICENSE for more details.
"""
import re
from collections import Mapping
from jinja2.runtime import Undefined
from jinja2._compat import text_type, string_types, integer_types
import decimal

number_re = re.compile(r'^-?d+(.d+)?$')
regex_type = type(number_re)


test_callable = callable


def test_odd(value):
    """Return true if the variable is odd."""
    return value % 2 == 1


def test_even(value):
    """Return true if the variable is even."""
    return value % 2 == 0


def test_divisibleby(value, num):
    """Check if a variable is divisible by a number."""
    return value % num == 0


def test_defined(value):
    """Return true if the variable is defined:

    .. sourcecode:: jinja

        {% if variable is defined %}
            value of variable: {{ variable }}
        {% else %}
            variable is not defined
        {% endif %}

    See the :func:`default` filter for a simple way to set undefined
    variables.
    """
    return not isinstance(value, Undefined)


def test_undefined(value):
    """Like :func:`defined` but the other way round."""
    return isinstance(value, Undefined)


def test_none(value):
    """Return true if the variable is none."""
    return value is None


def test_lower(value):
    """Return true if the variable is lowercased."""
    return text_type(value).islower()


def test_upper(value):
    """Return true if the variable is uppercased."""
    return text_type(value).isupper()


def test_string(value):
    """Return true if the object is a string."""
    return isinstance(value, string_types)


def test_mapping(value):
    """Return true if the object is a mapping (dict etc.).

    .. versionadded:: 2.6
    """
    return isinstance(value, Mapping)


def test_number(value):
    """Return true if the variable is a number."""
    return isinstance(value, integer_types + (float, complex, decimal.Decimal))


def test_sequence(value):
    """Return true if the variable is a sequence. Sequences are variables
    that are iterable.
    """
    try:
        len(value)
        value.__getitem__
    except:
        return False
    return True


def test_equalto(value, other):
    """Check if an object has the same value as another object:

    .. sourcecode:: jinja

        {% if foo.expression is equalto 42 %}
            the foo attribute evaluates to the constant 42
        {% endif %}

    This appears to be a useless test as it does exactly the same as the
    ``==`` operator, but it can be useful when used together with the
    `selectattr` function:

    .. sourcecode:: jinja

        {{ users|selectattr("email", "equalto", "foo@bar.invalid") }}

    .. versionadded:: 2.8
    """
    return value == other


def test_sameas(value, other):
    """Check if an object points to the same memory address than another
    object:

    .. sourcecode:: jinja

        {% if foo.attribute is sameas false %}
            the foo attribute really is the `False` singleton
        {% endif %}
    """
    return value is other


def test_iterable(value):
    """Check if it's possible to iterate over an object."""
    try:
        iter(value)
    except TypeError:
        return False
    return True


def test_escaped(value):
    """Check if the value is escaped."""
    return hasattr(value, '__html__')


def test_greaterthan(value, other):
    """Check if value is greater than other."""
    return value > other


def test_lessthan(value, other):
    """Check if value is less than other."""
    return value < other


TESTS = {
    'odd':              test_odd,
    'even':             test_even,
    'divisibleby':      test_divisibleby,
    'defined':          test_defined,
    'undefined':        test_undefined,
    'none':             test_none,
    'lower':            test_lower,
    'upper':            test_upper,
    'string':           test_string,
    'mapping':          test_mapping,
    'number':           test_number,
    'sequence':         test_sequence,
    'iterable':         test_iterable,
    'callable':         test_callable,
    'sameas':           test_sameas,
    'equalto':          test_equalto,
    'escaped':          test_escaped,
    'greaterthan':      test_greaterthan,
    'lessthan':         test_lessthan
}
所有测试器的源代码

    

  1.2 直接在模板的 {{}} 中书写书写对应的测试器即可    

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>demo01</title>
</head>
<body>
    <h2>测试器</h2>
    <hr />

    <h3>测试odd/even</h3>
    <p>{{ 3 is odd }}</p>
    <p>{{ 4 is even }}</p>
    <p>
        {% if (var01 is even) %}
            var01是偶数
        {% else %}
            var01不是偶数
        {% endif %}
    </p>
    <hr />

    <h3>测试test_divisibleby</h3>
    <p>
        {{ 4 is divisibleby 2 }}
        <br />
        {% if (var02 is divisibleby 2) %}
            var02能被2整除
        {% endif %}
    </p>
    <hr />

    <h3>测试test_defined/test_undefined</h3>
    <p>
        {{ var03 is defined }}
        <br />
        {% if var03 is defined %}
            var03已经被定义
        {% endif %}
        <br />
        {{ var04 is undefined }}
        <br />
        {% if var04 is undefined %}
            var04没有被定义
        {% endif %}
    </p>
    <hr />

    <h3>测试test_none</h3>
    <p>
        {{ var05 is none }}
        <br />
        {% if var05 is none %}
            var05的值是None
        {% endif %}
    </p>
    <hr />

    <h3>测试test_lower/test_upper</h3>
    <p>
        {{ var06 is lower }}
        <br />
        {% if var06 is lower %}
            var06的值全是小写
        {% endif %}
        <br />
        {{ var07 is upper }}
        <br />
        {% if var07 is upper %}
            var07的值全是大写
        {% endif %}
    </p>
    <hr />

    <h3>测试test_string</h3>
    <p>
        {{ var08 is string }}
        <br />
        {% if var08 is string %}
            var08的值是一个字符串
            {% else %}
            var08的值不是一个字符串
        {% endif %}
    </p>
    <hr />

    <h3>测试test_mapping</h3>
    <p>
        {{ var09 is mapping }}
        <br />
    </p>
    <hr />

    <h3>测试test_number</h3>
    <p>
        {{ var10 is number }}
        <br />
    </p>
    <hr />

    <h3>测试test_sequence</h3>
    <p>
        {{ var11 is sequence }}
        <br />
    </p>
    <hr />

    <h3>测试test_equalto</h3>
    <p>
        {{ var12 is equalto 'zeus' }}
        <br />
        {% if var12 is equalto 'zeus' %}
            var12的值是zeus
        {% endif %}
    </p>
    <hr />

    <h3>测试test_sameas</h3>
    <p>
        {{ var13 is sameas false }}
    </p>
    <hr />

    <h3>测试test_iterable</h3>
    <p>
        {{ var14 is iterable }}
    </p>
    <hr />

    <h3>测试test_escaped</h3>
    <p>
        {{ var15 is escaped }}
    </p>
    <hr />

    <h3>测试test_greaterthan</h3>
    <p>
        {{ 3 is greaterthan 2 }}
    </p>
    <hr />

    <h3>测试test_lessthan</h3>
    <p>
        {{ 3 is lessthan 4 }}
    </p>



{#    <h3>notes</h3>#}
    <p>
{#        {{ loop.length }}   循环总次数#}
{#        {{ loop.index }}  当前次数,下标从1开始#}
{#        {{ loop.index0 }} 当前次数,下标从0开始#}
{#        {{ loop.reindex }} 当前次数反向#}
{#        {{ loop.cycle('a','b','c') }}  循环自动返回元素  #}
{#        {{ loop.first }} 首次迭代时返回true#}
{#        {{ loop.last }} 首次迭代是返回false#}
    </p>
</body>
</html>
html模板代码
from flask import Blueprint
from flask import render_template
# from jinja2 import tests

bp_test = Blueprint('test', __name__)

@bp_test.route('/test/')
def test():
    content = {
        'name':'warrior',
        'var01': 3,
        'var02': 4,
        'var03': 5,
        'var05': None,
        'var06': 'warrior',
        'var07': 'WARRIOR',
        'var08': 234,
        'var09': {
            'name':"fury"
        },
        'var10': 14,
        'var11': 1324,
        'var12': 'zeus',
        'var13': False,
        'var14': 'warrior',
        'var15': 'good'
    }
    resp = render_template('demo01.html', **content)
    return resp
蓝图代码
from flask import Flask
from flask import render_template
from jinja2 import tests

from demo01 import bp_test

app = Flask(__name__)

app.register_blueprint(bp_test)

# @app.route('/')
# def hello_world():
#     resp = render_template('index.html', info='warrior')
#     return resp

print(app.url_map)

if __name__ == '__main__':
    app.run(debug=True)
python代码

2 控制语句

  在控制语句上的表达式不用写在 {{ }} 中;但是在控制语句中的表达式必须写在 {{ }} 中

  

  2.1 IF控制语句

{% if var01 < 5 %}
            条件1成立
            {% elif var01 < 10 %}
            条件2成立
            {% else %}
            条件1和2都不成立
{% endif %}

  2.2 FOR控制语句

% for foo in ['warrior', 'fury', 'zeus'] %}
            {{ foo }} <br />
{% endfor %}

  注意:在python代码中 for 和 else 搭配是循环完毕后执行else后面的语句;但是在Jinja2模板中却只有0次迭代(即:不进行迭代)时执行else后面的语句

{% for foo in var02 if foo == 'mother' %}
            {{ foo }} <br />
            {% else %}
            在var02中没有满足条件的元素
{% endfor %}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Controller</title>
</head>
<body>
    <h2>测试流程控制语句</h2>
    <hr />

    <h4>测试IF语句</h4>
    <p>
        {% if var01 < 5 %}
            条件1成立
            {% elif var01 < 10 %}
            条件2成立
            {% else %}
            条件1和2都不成立
        {% endif %}
    </p>
    <hr />

    <h4>测试FOR语句</h4>
    <p>
        {% for foo in ['warrior', 'fury', 'zeus'] %}
            {{ foo }} <br />
        {% endfor %}
        <hr />
        {% for foo in var02 if foo == 'mother' %}
            {{ foo }} <br />
            {% else %}
            在var02中没有满足条件的元素
        {% endfor %}
    </p>
</body>
</html>
html模板
from flask import Blueprint
from flask import render_template

bp_controller = Blueprint('controller', __name__)

@bp_controller.route('/controller/')
def control():
    content = {
        'var01': 199,
        'var02': ['good', 'boy']
    }
    resp = render_template('controller.html', **content)
    return resp;
蓝图代码
from flask import Flask
from flask import render_template
from jinja2 import tests

# from testor import bp_test
from controller import bp_controller

app = Flask(__name__)

# app.register_blueprint(bp_test)
app.register_blueprint(bp_controller)

# @app.route('/')
# def hello_world():
#     resp = render_template('index.html', info='warrior')
#     return resp

print(app.url_map)

if __name__ == '__main__':
    app.run(debug=True)
python代码

     2.2.1 FOR循环的补充

    <p>
{#        {{ loop.length }}   循环总次数#}
{#        {{ loop.index }}  当前次数,下标从1开始#}
{#        {{ loop.index0 }} 当前次数,下标从0开始#}
{#        {{ loop.reindex }} 当前次数反向#}
{#        {{ loop.cycle('a','b','c') }}  循环自动返回元素  #}
{#        {{ loop.first }} 首次迭代时返回true#}
{#        {{ loop.last }} 首次迭代是返回false#}
    </p>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>测试模板</title>
</head>
<body>
    <h2>这里是测试模板的内容</h2>
    {% for foo in range(10) %}
{#        <li>当前次数(从1开始):{{ loop.index }} --> 内容:{{ foo }}</li>#}
        <li>当前次数(从0开始):{{ loop.index0 }} --> 内容:{{ foo }}</li>
{#        <h2>{{ loop.length }}</h2>#}
{#        {{ loop.first }} #}
{#        {{ loop.last }}#}
    {% endfor %}

</body>
</html>
html模板
from flask import Blueprint
from flask import render_template

bp_test = Blueprint('test', __name__, url_prefix='/test')

@bp_test.route('/test/')
def test():
    return render_template('test.html')
蓝图代码
from flask import Flask
from flask import url_for

# from bp_include import bp_test
# from bp_extends import bp_extends
from bp_test import bp_test

app = Flask(__name__)

# app.register_blueprint(bp_test)
# app.register_blueprint(bp_extends)
app.register_blueprint(bp_test)


@app.route('/')
def hello_world():
    return 'Hello World!'

print(app.url_map)

if __name__ == '__main__':
    app.run(debug=True)
python代码

3 赋值

  3.1 变量赋值

    {% set 变量名 =  值 %}

<h4>变量赋值</h4>
    <p>
        {% set student = 'warrior' %}
        学生姓名:{{ student }}
        <hr />
        {% set students = ['fury','zeus','warrior'] %}
        <p>
            {% for student in students %}
                {{ student }} <br />
            {% endfor %}

        </p>
    </p>

  3.2 块赋值

<h4>块赋值</h4>
    <p>
        {% set xxx %}
            <li>Hello Boy</li>
            <li>Hello World</li>
        {% endset %}
        {{ xxx }}
    </p>

4 作用域

  IF语句没有作用域,FOR语句有作用域;其它的{% %}通常产生作用域

  4.1 测试IF语句没有作用域

    

  4.2 设置IF语句的作用域

    利用块级作用域来设置IF语句的作用域

    

  4.3 测试FOR语句有作用域

    

  

5 块级作用域

{% with %}
    块级作用域中的内容
{% endwith %}

  5.1 不要在with上这样写

      

      会出现以下的报错信息

        

          原因:造成了变量污染

  5.2 解决办法

    

 1 流程控制:
 2     if
 3         测试
 4             测试器(一个函数) from jinja2 import tests
 5             is 后面跟的必须是个测试器
 6 
 7     for
 8         和else搭配 不是表示正常迭代完
 9         而是表示 0次迭代,或全部被 if 过滤  {% for i in xxx if ... %}
10 
11 
12 赋值:
13     变量赋值
14     块赋值
15 
16     好处:
17         1.中间变量
18         2.方便测试
19 
20 作用域:
21     if不产生作用域
22     for 产生作用域
23     其他的{% %}通常产生作用域
24 
25 构造局部作用域
26     with
27         不要在 with 写这种 :  {% with name=[1,2], xx=name[1] %}
28 
29 
30         应该要
31             {% with name=[1,2]
32                 {% set xx=name[1] %}
33             {% endwith %}
34         
35         好处: 防止变量污染
36 
37 
38 注意! 所有的语句标签,都必须要 {% xx %} {% endxx %}
39 
40 
41 
42 
43 小练习:
44 1. 把所有的测试器,都测试一遍
45 2. 把上次的按个导航条,改进以下,如果render_template('xx.html', user=user)
46     那么就通过if判断,如果有这个user那么就显示用域名
47     如果没有user,或者user是个None就 显示登陆注册
48     logo左浮动   右边写 login-group,右浮动
49 3. 传一个老列表,在模板里面用for迭代渲染li标签
思维笔记

6 模拟登录

  要求:如果用户名和密码都正确就显示  欢迎 XXX,否则就显示  登录和注册

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登录</title>
    <style>
        #head {
            background-color: skyblue;
            border: 1px solid red;
        }
        li {
            list-style-type: none;
        }
        .group-item {
            float: left;
            padding:0 10px;
        }
        .login-item {
            float: right;
            padding:0 10px;
        }
        .clear {
            clear: both;
        }
        a {
            text-decoration: none;
        }
        li:hover {
            background-color: blue
        }
        a:hover {
            color: yellow;
        }
    </style>
</head>
<body>
    <div id="head">
        <ul>
            <li class="group-item"><a href="#">首页</a></li>
            <li class="group-item"><a href="#">python</a></li>
            <li class="group-item"><a href="#">java</a></li>
            <li class="group-item"><a href="#">angular</a></li>
            {% if (name is equalto "warrior") and (pwd is equalto "123321") %}
                <li class="login-item"><span>欢迎&nbsp;{{ name }}</span></li>
            {% else %}
                <li class="login-item"><a href="#">登录</a></li>
                <li class="login-item"><a href="#">注册</a></li>
            {% endif %}
            <div class="clear"></div>
        </ul>
    </div>
</body>
</html>
htmo模板代码
from flask import Blueprint
from flask import render_template

bp_login = Blueprint("login", __name__)

@bp_login.route('/login/')
def toLogin():
    content = {
        'name': 'warrior',
        'pwd': '123321'
    }
    resp = render_template('login.html', **content)
    return resp
蓝图代码
 1 from flask import Flask
 2 from flask import render_template
 3 from jinja2 import tests
 4 
 5 # from testor import bp_test
 6 # from controller import bp_controller
 7 from login import bp_login
 8 
 9 app = Flask(__name__)
10 
11 # app.register_blueprint(bp_test)
12 # app.register_blueprint(bp_controller)
13 app.register_blueprint(bp_login)
14 
15 # @app.route('/')
16 # def hello_world():
17 #     resp = render_template('index.html', info='warrior')
18 #     return resp
19 
20 print(app.url_map)
21 
22 if __name__ == '__main__':
23     app.run(debug=True)
python代码

原文地址:https://www.cnblogs.com/NeverCtrl-C/p/7554680.html