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>
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)
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>
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)
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>
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)
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>欢迎 {{ 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>
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)