快乐学习
前程无忧、中华英才非你莫属!

Flask入门到精通-Day3

一、Flask的模板 Jinja2详解
 
 
1、Jinja2概念
Jinja2是一个现代的,设计师友好的Python模板语言,模仿Django的模板。使用可选的沙盒模板执行环境,它具有快速,广泛使用和安全性:
 
2、首先安装
pip install Jinja2
 
3、在flask中把后台的数据传递给,jijina2 的模板的方法。
render_template(模板的名称,模板上下文可用的变量)

 

  
4、Jinja2的语法格式
 
     在jinja2中,存在三种语法:
  1. 控制结构 , 运行Jinja2的语句块 {% %}
  2. 变量取值, 在页面中打印Jinja2运行的结果 {{ }}
  3. 注释 {# #}
5、行语句
前缀可以出现在一行的任意位置,只要它前面没有文本。为了语句有更好的可读 性,在块的开始(比如 for  if  elif 等等)以冒号结尾:
# for item in seq:
# endfor
{% for item in seq %}
<li>{{ item }}</li>
{% endfor %}
同样的意思。好处是:若有未闭合的圆括号、花括号或方括号,行语句可以跨越多行。
6、注释
 
## this comment is ignored
或者 {# … #}
在模板中,Jinja2支持使用“.”获取变量的属性,比如user字典中的username键值通过“.”获取,即user.username,在效果上等同于user[‘username’]
 
7、模板继承
Jinja 中最强大的部分就是模板继承。模板继承允许你构建一个包含你站点共同元素的基 本模板“骨架”,并定义子模板可以覆盖的  
听起来复杂,实际上很简单。从例子上手是最易于理解的。

基本模板

这个模板,我们会把它叫做 base.html ,定义了一个简单的 HTML 骨架文档,你可 能使用一个简单的两栏页面。用内容填充空的块是子模板的工作:
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.01//EN”><html lang=”en”><html xmlns=”http://www.w3.org/1999/xhtml”>
<head>
{% block head %}
<link rel=”stylesheet” href=”style.css” />
<title>{% block title %}{% endblock %} – My Webpage</title>
{% endblock %}
</head>
<body>
<div id=”content”>{% block content %}{% endblock %}</div>
<div id=”footer”>
{% block footer %}
&copy; Copyright 2008 by <a href=”http://domain.invalid/”>you</a>.
{% endblock %}
</div>
</body>
在本例中, {% block %} 标签定义了四个字幕版可以填充的块。所有的 block 标签 告诉模板引擎子模板可以覆盖模板中的这些部分。

子模板

一个子模板看起来是这样:
{% extends “base.html” %}
{% block title %}Index{% endblock %}
{% block head %}
{{ super() }}
    <style type=”text/css”>
        .important { color: #336699; }
    </style>
{% endblock %}
{% block content %}
<h1>Index</h1>
<p class=”important”>
Welcome on my awesome homepage.
</p>
{% endblock %}
{% extend %} 标签是这里的关键。它告诉模板引擎这个模板“继承”另一个模板。 当模板系统对这个模板求值时,首先定位父模板。 extends 标签应该是模板中的第一个 标签。它前面的所有东西都会按照普通情况打印出来,而且可能会导致一些困惑。更多 该行为的细节以及如何利用它,见 Null-Master 退回
模板的文件名依赖于模板加载器。例如 FileSystemLoader 允许你用文件名访 问其它模板。你可以使用斜线访问子目录中的模板:
{% extends “layout/default.html” %}
这种行为也可能依赖于应用内嵌的 Jinja 。注意子模板没有定义 footer 块,会 使用父模板中的值。
你不能在同一个模板中定义多个同名的 {% block %} 标签。因为块标签以两种 方向工作,所以存在这种限制。即一个块标签不仅提供一个可以填充的部分,也在父级 定义填充的内容。如果同一个模板中有两个同名的 {% blok %} 标签,父模板 无法获知要使用哪一个块的内容。
如果你想要多次打印一个块,无论如何你可以使用特殊的 self 变量并调用与块同名 的函数:
<title>{% block title %}{% endblock %}</title>
<h1>{{ self.title() }}</h1>
{% block body %} xxx{% endblock %}

Super 块

可以调用 super 来渲染父级块的内容。这会返回父级块的结果:
{% block sidebar %}
<h3>Table Of Contents</h3>
{{ super() }}
{% endblock %}

命名块结束标签

Jinja2 允许你在块的结束标签中加入的名称来改善可读性:
{% block sidebar %}
{% block inner_sidebar %}
{% endblock inner_sidebar %}{% endblock sidebar %}
无论如何, endblock 后面的名称一定与块名匹配。

嵌套块和作用域

嵌套块可以胜任更复杂的布局。而默认的块不允许访问块外作用域中的变量:
{% for item in seq %}
<li>{% block loop_item %}{{ item }}{% endblock %}</li>{% endfor %}
这个例子会输出空的 <li> 项,因为 item 在块中是不可用的。其原因是,如果 块被子模板替换,变量在其块中可能是未定义的或未被传递到上下文。
从 Jinja 2.2 开始,你可以显式地指定在块中可用的变量,只需在块声明中添加 scoped 修饰,就把块设定到作用域中:
{% for item in seq %}
<li>{% block loop_item scoped %}{{ item }}{% endblock %}</li>{% endfor %}
当覆盖一个块时,不需要提供 scoped 修饰。

模板对象

Changed in version 2.4.
当一个模板对象被传递到模板上下文,你也可以从那个对象继承。假设调用 代码传递 layout_template 布局模板到环境,这段代码会工作:
{% extends layout_template %}
之前 layout_template 变量一定是布局模板文件名的字符串才能工作。

8、变量

模板变量由传递给模板的上下文字典定义
{{ foo.bar }}
 
{{ foo[‘bar’] }}

9、控制语句

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

遍历序列中的每项。例如,要显示一个由 users` 变量提供的用户列表:
<h1>Members</h1>
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% endfor %}
</ul>
因为模板中的变量保留它们的对象属性,可以迭代像 dict 的容器:
<dl>
{% for key, value in my_dict.iteritems() %}
<dt>{{ key|e }}</dt>
<dd>{{ value|e }}</dd>{% endfor %}
</dl>
注意无论如何字典通常是无序的,所以你可能需要把它作为一个已排序的列表传入 到模板或使用 dictsort 过滤器。
在一个 for 循环块中你可以访问这些特殊的变量:
变量
描述
loop.index
当前循环迭代的次数(从 1 开始)
loop.index0
当前循环迭代的次数(从 0 开始)
loop.revindex
到循环结束需要迭代的次数(从 1 开始)
loop.revindex0
到循环结束需要迭代的次数(从 0 开始)
loop.first
如果是第一次迭代,为 True 。
loop.last
如果是最后一次迭代,为 True 。
loop.length
序列中的项目数。
loop.cycle
在一串序列间期取值的辅助函数。见下面的解释。
在 for 循环中,可以使用特殊的 loop.cycle 辅助函数,伴随循环在一个字符串/变 量列表中周期取值:
{% for row in rows %}
<li class={{ loop.cycle(‘odd’, ‘even’) }}>{{ row }}</li>
{% endfor %}
从 Jinja 2.1 开始,一个额外的 cycle 辅助函数允许循环限定外的周期取值。 更多信息请阅读 全局函数清单 
与 Python 中不同,模板中的循环内不能 break  continue 。但你可以在迭代 中过滤序列来跳过项目。下面的例子中跳过了所有隐藏的用户:
{% for user in users if not user.hidden %}
<li>{{ user.username|e }}</li>{% endfor %}
好处是特殊的 loop 可以正确地计数,从而不计入未迭代过的用户。
如果因序列是空或者过滤移除了序列中的所有项目而没有执行循环,你可以使用 else 渲染一个用于替换的块:
<ul>{% for user in users %}
<li>{{ user.username|e }}</li>{% else %}
<li><em>no users found</em></li>{% endfor %}</ul>
也可以递归地使用循环。当你处理诸如站点地图之类的递归数据时很有用。要递归地 使用循环,你只需要在循环定义中加上 recursive 修饰,并在你想使用递归的地 方,对可迭代量调用 loop 变量。
下面的例子用递归循环实现了站点地图:
<ul class=“sitemap”>{% for item in sitemap recursive %}
<li><a href={{ item.href|e }}>{{ item.title }}</a>
{% if item.children –%}
<ul class=“submenu”>{{ loop(item.children) }}</ul>
{% endif %}</li>{% endfor %}</ul>

If

Jinja 中的 if 语句可比 Python 中的 if 语句。在最简单的形式中,你可以测试 一个变量是否未定义,为空或 false:
{% if users %}<ul>{% for user in users %}
<li>{{ user.username|e }}</li>{% endfor %}</ul>{% endif %}
像在 Python 中一样,用 elif  else 来构建多个分支。你也可以用更复杂的 表达式:
{% if kenny.sick %}
Kenny is sick.
{% elif kenny.dead %}
You killed Kenny! You bastard!!!
{% else %}
Kenny looks okay — so far
{% endif %}
If 也可以被用作 内联表达式 并作为 循环过滤 

宏类似常规编程语言中的函数。它们用于把常用行为作为可重用的函数,取代 手动重复的工作。
这里是一个宏渲染表单元素的小例子:
{% macro input(name, value=, type=‘text’, size=20) –%}
<input type={{ type }} name={{ name }} value={{
value|e }} size={{ size }}>{% endmacro %}
在命名空间中,宏之后可以像函数一样调用:
<p>{{ input(‘username’) }}</p><p>{{ input(‘password’, type=‘password’) }}</p>
如果宏在不同的模板中定义,你需要首先使用 import 
在宏内部,你可以访问三个特殊的变量:
varargs
如果有多于宏接受的参数个数的位置参数被传入,它们会作为列表的值保存在varargs 变量上。
kwargs
同 varargs ,但只针对关键字参数。所有未使用的关键字参数会存储在 这个特殊变量中。
caller
如果宏通过 call 标签调用,调用者会作为可调用的宏被存储在这个 变量中。
宏也可以暴露某些内部细节。下面的宏对象属性是可用的:
name
宏的名称。 {{ input.name }} 会打印 input 。
arguments
一个宏接受的参数名的元组。
defaults
默认值的元组。
catch_kwargs
如果宏接受额外的关键字参数(也就是访问特殊的 kwargs 变量),为 true 。
catch_varargs
如果宏接受额外的位置参数(也就是访问特殊的 varargs 变量),为 true 。
caller
如果宏访问特殊的 caller 变量且由 call 标签调用,为 true 。
如果一个宏的名称以下划线开始,它不是导出的且不能被导入。

调用

在某些情况下,需要把一个宏传递到另一个宏。为此,可以使用特殊的 call 块。 下面的例子展示了如何让宏利用调用功能:
{% macro render_dialog(title, class=‘dialog’) –%}
<div class={{ class }}>
<h2>{{ title }}</h2>
<div class=“contents”>
{{ caller() }}
</div>
</div>{% endmacro %}
{% call render_dialog(‘Hello World’) %}
This is a simple dialog rendered by using a macro and
a call block.
{% endcall %}
也可以向调用块传递参数。这在为循环做替换时很有用。总而言之,调用块的工作方 式几乎与宏相同,只是调用块没有名称。
这里是一个带参数的调用块的例子:
{% macro dump_users(users) –%}
<ul>
{% for user in users %}
<li><p>{{ user.username|e }}</p>{{ caller(user) }}</li>
{% endfor %}
</ul>{% endmacro %}
{% call(user) dump_users(list_of_user) %}
<dl>
<dl>Realname</dl>
<dd>{{ user.realname|e }}</dd>
<dl>Description</dl>
<dd>{{ user.description }}</dd>
</dl>{% endcall %}

过滤器

过滤器段允许你在一块模板数据上应用常规 Jinja2 过滤器。只需要把代码用 filter 节包裹起来:
{% filter upper %}
This text becomes uppercase
{% endfilter %}

赋值

在代码块中,你也可以为变量赋值。在顶层的(块、宏、循环之外)赋值是可导出的,即 可以从别的模板中导入。
赋值使用 set 标签,并且可以为多个变量赋值:
{% set navigation = [(‘index.html’, ‘Index’), (‘about.html’, ‘About’)] %}{% set key, value = call_something() %}

继承

extends 标签用于从另一个模板继承。你可以在一个文件中使用多次继承,但是 只会执行其中的一个。见上面的关于 模板继承 的节。

块用于继承,同时作为占位符和用于替换的内容。 模板继承 节中详细地介绍了块。

包含

include 语句用于包含一个模板,并在当前命名空间中返回那个文件的内容渲 染结果:
{% include ‘header.html’ %}
Body
{% include ‘footer.html’ %}
被包含的模板默认可以访问活动的上下文中的变量。更多关于导入和包含的上下文 行为见 导入上下文行为 
从 Jinja 2.2 开始,你可以把一句 include 用 ignore missing 标记,这样 如果模板不存在,Jinja 会忽略这条语句。当与 with  without context 语句联合使用时,它必须被放在上下文可见性语句 之前 。这里是一些有效的例 子:
{% include “sidebar.html” ignore missing %}{% include “sidebar.html” ignore missing with context %}{% include “sidebar.html” ignore missing without context %}
New in version 2.2.
你也可以提供一个模板列表,它会在包含前被检查是否存在。第一个存在的模板会 被包含进来。如果给出了 ignore missing ,且所有这些模板都不存在,会退化 至不做任何渲染,否则将会抛出一个异常。
例子:
{% include [‘page_detailed.html’, ‘page.html’] %}{% include [‘special_sidebar.html’, ‘sidebar.html’] ignore missing %}
Changed in version 2.4: 如果传递一个模板对象到模板上下文,你可以用 include 包含这个对 象。

导入

Jinja2 支持在宏中放置经常使用的代码。这些宏可以被导入,并不同的模板中使用。这 与 Python 中的 import 语句类似。要知道的是,导入量会被缓存,并且默认下导入的 模板不能访问当前模板中的非全局变量。更多关于导入和包含的上下文行为见 导入上下文行为
有两种方式来导入模板。你可以把整个模板导入到一个变量或从其中导入请求特定的宏 /导出量。
比如我们有一个渲染表单(名为 forms.html )的助手模块:
{% macro input(name, value=, type=‘text’) –%}
<input type={{ type }} value={{ value|e }} name={{ name }}>{% endmacro %}
{% macro textarea(name, value=, rows=10, cols=40) –%}
<textarea name={{ name }} rows={{ rows }} cols={{ cols
}}>{{ value|e }}</textarea>{% endmacro %}
最简单灵活的方式是把整个模块导入为一个变量。这样你可以访问属性:
{% import ‘forms.html’ as forms %}<dl>
<dt>Username</dt>
<dd>{{ forms.input(‘username’) }}</dd>
<dt>Password</dt>
<dd>{{ forms.input(‘password’, type=‘password’) }}</dd></dl><p>{{ forms.textarea(‘comment’) }}</p>
此外你也可以从模板中导入名称到当前的命名空间:
{% from ‘forms.html’ import input as input_field, textarea %}<dl>
<dt>Username</dt>
<dd>{{ input_field(‘username’) }}</dd>
<dt>Password</dt>
<dd>{{ input_field(‘password’, type=‘password’) }}</dd></dl><p>{{ textarea(‘comment’) }}</p>
名称以一个或更多下划线开始的宏和变量是私有的,不能被导入。
Changed in version 2.4: 如果传递一个模板对象到模板上下文,从那个对象中导入。
 

空白控制

您也可以手动剥离模板中的空白。如果将减号(添加到块的开头或结尾(例如For标签),注释或变量表达式,则将删除该块之前或之后的空格:
您可以通过在块的开头放置加号(+来手动禁用lstrip_blocks行为
<div>
{%+ if something %}yay{% endif %}
</div>

逃避

对于更大的部分,标记块原始是有意义的例如,要在模板中包含示例Jinja语法,您可以使用以下代码段:
{% raw %}
<ul>
{% for item in seq %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% endraw %}
 
 

 
 
10、导入上下文行为
默认下,每个包含的模板会被传递到当前上下文,而导入的模板不会。这样做的原因 是导入量不会像包含量被缓存,因为导入量经常只作容纳宏的模块。
无论如何,这当然也可以显式地更改。通过在 import/include 声明中直接添加 with context  without context ,当前的上下文可以传递到模板,而且不会 自动禁用缓存。
这里有两个例子:
{% from ‘forms.html’ import input with context %}{% include ‘header.html’ without context %}
提示
在 Jinja 2.0 中,被传递到被包含模板的上下文不包含模板中定义的变量。 事实上,这不能工作:
{% for box in boxes %}
{% include “render_box.html” %}{% endfor %}
在 Jinja 2.0 中,被包含的模板 render_box.html 不能 访问 box 。从 Jinja 2.1 开始, render_box.html 可以 这么做。

表达式

Jinja 中到处都允许使用基本表达式。这像常规的 Python 一样工作,即使你不用 Python 工作,你也会感受到其带来的便利。

字面量

表达式最简单的形式就是字面量。字面量表示诸如字符串和数值的 Python 对象。下面 的字面量是可用的:
“Hello World”:
双引号或单引号中间的一切都是字符串。无论何时你需要在模板中使用一个字 符串(比如函数调用、过滤器或只是包含或继承一个模板的参数),它们都是 有用的。
42 / 42.23:
直接写下数值就可以创建整数和浮点数。如果有小数点,则为浮点数,否则为 整数。记住在 Python 里, 42 和 42.0 是不一样的。
[‘list’, ‘of’, ‘objects’]:
一对中括号括起来的东西是一个列表。列表用于存储和迭代序列化的数据。例如 你可以容易地在 for 循环中用列表和元组创建一个链接的列表:
<ul>{% for href, caption in [(‘index.html’, ‘Index’), (‘about.html’, ‘About’),
(‘downloads.html’, ‘Downloads’)] %}
<li><a href={{ href }}>{{ caption }}</a></li>{% endfor %}</ul>
(‘tuple’, ‘of’, ‘values’):
元组与列表类似,只是你不能修改元组。如果元组中只有一个项,你需要以逗号 结尾它。元组通常用于表示两个或更多元素的项。更多细节见上面的例子。
{‘dict’: ‘of’, ‘key’: ‘and’, ‘value’: ‘pairs’}:
Python 中的字典是一种关联键和值的结构。键必须是唯一的,并且键必须只有一个 值。字典在模板中很少使用,罕用于诸如 xmlattr() 过滤器之类。
true / false:
true 永远是 true ,而 false 始终是 false 。
提示
特殊常量 true  false  none 实际上是小写的。因为这在过去会导致 混淆,过去 True扩展为一个被认为是 false 的未定义的变量。所有的这三个 常量也可以被写成首字母大写( True  False  None )。尽管如此, 为了一致性(所有的 Jinja 标识符是小写的),你应该使用小写的版本。

算术

Jinja 允许你用计算值。这在模板中很少用到,但是为了完整性允许其存在。支持下面的 运算符:
+
把两个对象加到一起。通常对象是素质,但是如果两者是字符串或列表,你可以用这 种方式来衔接它们。无论如何这不是首选的连接字符串的方式!连接字符串见 ~ 运算符。 {{ 1 + 1 }} 等于 2 。
用第一个数减去第二个数。 {{ 3 – 2 }} 等于 1 。
/
对两个数做除法。返回值会是一个浮点数。 {{ 1 / 2 }} 等于 {{ 0.5 }} 。
//
对两个数做除法,返回整数商。 {{ 20 // 7 }} 等于 2 。
%
计算整数除法的余数。 {{ 11 % 7 }} 等于 4 。
*
用右边的数乘左边的操作数。 {{ 2 * 2 }} 会返回 4 。也可以用于重 复一个字符串多次。 {{ ‘=’ * 80 }} 会打印 80 个等号的横条。
**
取左操作数的右操作数次幂。 {{ 2**3 }} 会返回 8 。

比较

==
比较两个对象是否相等。
!=
比较两个对象是否不等。
>
如果左边大于右边,返回 true 。
>=
如果左边大于等于右边,返回 true 。
<
如果左边小于右边,返回 true 。
<=
如果左边小于等于右边,返回 true 。

逻辑

对于 if 语句,在 for 过滤或 if 表达式中,它可以用于联合多个表达式:
and
如果左操作数和右操作数同为真,返回 true 。
or
如果左操作数和右操作数有一个为真,返回 true 。
not
对一个表达式取反(见下)。
(expr)
表达式组。
提示
is  in 运算符同样支持使用中缀记法: foo is not bar  foo not in bar 而不是 not foois bar  not foo in bar 。所有的 其它表达式需要前缀记法 not (foo and bar) 

其它运算符

下面的运算符非常有用,但不适用于其它的两个分类:
in
运行序列/映射包含检查。如果左操作数包含于右操作数,返回 true 。比如 {{ 1 in[1,2,3] }} 会返回 true 。
is
运行一个 测试 。
|
应用一个 过滤器 。
~
把所有的操作数转换为字符串,并且连接它们。 {{ “Hello ” ~ name ~ “!” }} 会返回(假设 name 值为 ”John’ ) Hello John! 。
()
调用一个可调用量:{{ post.render() }} 。在圆括号中,你可以像在 python 中一样使用位置参数和关键字参数: {{ post.render(user, full=true) }} 。
. / []
获取一个对象的属性。(见 变量 )

If 表达式

同样,也可以使用内联的 if 表达式。这在某些情况很有用。例如你可以用来在一个 变量定义的情况下才继承一个模板,否则继承默认的布局模板:
{% extends layout_template if layout_template is defined else ‘master.html’ %}
一般的语法是 <do something> if <something is true> else <do something else> 
else 部分是可选的。如果没有显式地提供 else 块,会求值一个未定义对象:
{{ ‘[%s]’ % page.title if page.title }}
 
 
 
全局函数
1、 range([start, ]stop[, step])
列表中有7个用户,但是您希望渲染三个空项以使用CSS强制执行高度:<ul>{% for user in users %}
<li>{{ user.username }}</li>{% endfor %}{% for number in range(10 – users|count) %}
<li class=“empty”><span>…</span></li>{% endfor %}</ul>
2、 lipsumn = 5html = Truemin = 20max = 100 
为模板生成一些lorem ipsum。默认情况下,会生成五个HTML段落,每个段落介于20到100个单词之间。如果html为False,则返回常规文本。这对于生成布局测试的简单内容很有用。
3、 dict(**items)
dict文字的一个方便的替代品。 是一样的{‘foo’: ‘bar’}dict(foo=’bar’)
4、 class cycler(*items)
{% set row_class = cycler(‘odd’, ‘even’) %}
<ul class=“browser”>{% for folder in folders %}
<li class=“folder {{ row_class.next() }}>{{ folder|e }}</li>{% endfor %}{% for filename in files %}
<li class=“file {{ row_class.next() }}>{{ filename|e }}</li>{% endfor %}</ul>
循环仪,可以循环类似于如何值之间loop.cycle 工作。loop.cycle不同,您可以在循环之外或多个循环之外使用此循环器。
如果要显示文件夹列表并且文件夹位于顶部但是在同一列表中具有交替的行颜色,则此功能非常有用。
循环仪具有以下属性和方法:
reset
将循环重置为第一个项目。
next
前进一个项目并返回当前项目。
current
返回当前项。
5、 class joinersep =’ 
{% set pipe = joiner(“|”) %}{% if categories %} {{ pipe() }}
Categories: {{ categories|join(“, “) }}{% endif %}{% if author %} {{ pipe() }}
Author: {{ author() }}{% endif %}{% if can_edit %} {{ pipe() }}
<a href=“?action=edit”>Edit</a>{% endif %}
一个小帮手,可用于“连接”多个部分。
6、 class namespace 
{% set ns = namespace() %}
{% set ns.foo = ‘bar’ %}
创建一个允许使用标记进行属性赋值的新容器 {% set %}。 其主要目的是允许从循环体内携带值到外部范围

过滤器

变量可以通过过滤器修改过滤器通过管道符号(|)与变量分隔,并且在括号中可以包含可选参数。可以链接多个过滤器。一个过滤器的输出应用于下一个过滤器
例如 {{ name| striptags| title }} 会移除 name 中的所有 HTML 标签并且改写 为标题样式的大小写格式。过滤器接受带圆括号的参数,如同函数调用。这个例子会 把一个列表用逗号连接起来: {{ list | join(‘, ‘) }} 
 
 
实例:
  <h1>Hello {{ name | upper | truncate(3, True) }}!</h1>
现在name变量不但被转换为大写,而且当它的长度大于3后,只显示前3个字符,后面默认用”…”显示。过滤器”truncate”有3个参数,第一个是字符截取长度;第二个决定是否保留截取后的子串,默认是False,也就是当字符大于3后,只显示”…”,截取部分也不出现;第三个是省略符号,默认是”…”。
其实从例子中我们可以猜到,过滤器本质上就是一个转换函数,它的第一个参数就是待过滤的变量,在模板中使用时可以省略去。如果它有第二个参数,模板中就必须传进去。
内置过滤器函数
1、abs(number)
返回一个数值的绝对值
2、attrobjname
获取对象的属性
3、batch(value, linecount, fill_with=None)
接 受的value是一个序列对象, linecount表明个数, 最后生成一个列表, 列表个数为linecount, 如果提供的value长度小于 linecount, 不足的使用fill_with填充
4、capitalize(s)
接受一个字符串, 将其转换为首字母大写, 其他字母小写的形式返回
5、center(value, width=80)
接受一个字符串, 将其至于80的长度中居中, 不足的字符使用空格填充
6、default(value, default_value=u”, boolean=False)
返回value指定的变量的值, 如果value是Undefined那么返回default_value指定的值, boolean意义未知
7、 dictsortvaluecase_sensitive = Falseby =’key’reverse = False
value 为要遍历的字典, case_sensitive指示是否立即加载, 设置为False表示延时加载, by表示以什么排序, 可以通过设置 by = ‘value’来以值排序. reverse是顺序还是逆序。
8、 escapes
将字符串s中的字符&,<,>,’和“转换为HTML安全序列。如果需要在HTML中显示可能包含此类字符的文本,请使用此选项。将返回值标记为标记字符串。
别名:
e
9、 filesizeformatvaluebinary = False
接受一个数值, 返回人易读的文件大小表示.
10、 firstseq
返回序列的第一个元素
11、 float(value, default = 0.0)
将接受到的value转换成float类型, 如果转换失败返回指定的default值
12、 forceescape(value
实施HTML转义
13、 format(value, *args, **kwargs)
类似于字符串格式化’%d     %s’这样的功能value是格式定义, attribute不定参数接受占位符代表的值.
{{ “%s – %s”|format(“Hello?”, “Foo!”) }} -> Hello? – Foo!
 
14、 groupby(value, attribute)
<ul>{% for group in persons|groupby(‘gender’) %}
<li>{{ group.grouper }}<ul>
{% for person in group.list %}
<li>{{ person.first_name }} {{ person.last_name }}</li>
{% endfor %}</ul></li>{% endfor %}</ul>
按照指定的共有属性将集合进行分组, 返回元组组成的列表, 元组中第一个元素是用来分组的属性的值, 第二个元素是分组得到的所有原集合元素的列表。
例如,如果您有一个表示具有genderfirst_namelast_name属性的人的dicts或对象列表,并且您希望按性别对所有用户进行分组,
 
 
15、 indentswidth = 4first = Falseblank = Falseindentfirst = None
返回字符串的副本,每行缩进4个空格。默认情况下,第一行和空行不缩进。参数:
  • width – 要缩进的空格数。
  • first– 不要跳过缩进第一行。
  • blank– 不要跳过缩进空行。
16、 int(value, default=0, base=10)
将值转换为整数。如果转换不起作用,它将返回0
17、 join(value, d=u”, attribute=None)
返回一个字符串,该字符串是序列中字符串的串联。{{ [1, 2, 3]|join(‘|’) }} -> 1|2|3
18、 last(seq)
返回序列的最后一项
19、 length(object)
返回序列或映射的项目数, 别名:count
20、 list(value)
将值转换为列表。如果它是一个字符串,则返回的列表将是一个字符列表
21、 lower(s)
将值转换为小写
22、 map()
对一系列对象应用过滤器或查找属性。
您有一个用户列表,但您只对用户名列表感兴趣:
Users on this page: {{ users|map(attribute=‘username’)|join(‘, ‘) }} 或者 通过传递过滤器的名称和之后的参数来让它调用过滤器:Users on this page: {{ titles|map(‘lower’)|join(‘, ‘) }}
23、 maxvaluecase_sensitive = Falseattribute = None
返回序列中最大的项目。{{ [1, 2, 3]|max }} -> 3
  • case_sensitive – 将大写和小写字符串视为不同。
  • attribute – 获取具有此属性的最大值的对象。
24、 minvaluecase_sensitive = Falseattribute = None
返回序列中的最小项,{{ [1, 2, 3]|min }} -> 1
 
  • case_sensitive – 将大写和小写字符串视为不同。
  • attribute – 获取具有此属性的最大值的对象
25、 pprint(value, verbose=False)
漂亮打印一个变量。用于调试。
26、 random(seq)
从序列中返回一个随机项
27、 reject()
通过对每个对象应用测试来过滤一系列对象,并在测试成功时拒绝对象。
如果未指定测试,则每个对象将被计算为布尔值。
28、 rejectattr()
通过将测试应用于每个对象的指定属性来过滤一系列对象,并在测试成功时拒绝这些对象。
29、 replacesoldnewcount = None
{{ “Hello World”|replace(“Hello”, “Goodbye”) }} -> Goodbye World
{{ “aaaaargh”|replace(“a”, “d’oh, “, 2) }} -> d’oh, d’oh, aaargh
返回值的副本,其中所有出现的子字符串都替换为新的子字符串。第一个参数是应该替换的子字符串,第二个是替换字符串。如果给出了可选的第三个参数count,则仅count替换第一个 匹配项:
30、 reverse(value)
反转对象或返回迭代器,迭代器以相反的方式迭代它。
31、 round(value, precision=0, method=’common’)
{{ 42.55|round }} -> 43.0{{ 42.55|round(1, ‘floor’) }} -> 42.5, 请注意,即使舍入为0精度,也会返回float。如果你需要一个真正的整数,通过int管道{{ 42.55|round|int }} -> 43
将数字四舍五入到给定的精度。第一个参数指定精度(默认为0),第二个参数指定舍入方法:
  • ‘common’ 向上或向下舍入
  • ‘ceil’ 总是围捕
  • ‘floor’ 总是四舍五入
如果未指定使用方法‘common’
32、 safe(value)
将值标记为安全,这意味着在启用了自动转义的环境中,此变量不会被转义
33、 select()
{{ numbers|select(“odd”) }}{{ numbers|select(“odd”) }}{{ numbers|select(“divisibleby”, 3) }}{{ numbers|select(“lessthan”, 42) }}{{ strings|select(“equalto”, “mystring”) }}
通过对每个对象应用测试来过滤一系列对象,并仅选择测试成功的对象, 如果未指定测试,则每个对象将被计算为布尔值
34、 selectattr()
{{ users|selectattr(“is_active”) }}{{ users|selectattr(“email”, “none”) }}
通过将测试应用于每个对象的指定属性来过滤一系列对象,并仅选择测试成功的对象。
35、 slicevalueslicesfill_with = None
<div class=“columwrapper”>
{% for column in items|slice(3) %}
<ul class=“column-{{ loop.index }}>
{% for item in column %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% endfor %}</div>
切片迭代器并返回包含这些项的列表列表。如果要创建包含表示列的三个ul标记的div,则非常有用: 接受一个可迭代对象, 返回slices指定的前n个元素, 不足n个使用fill_width指定的对象进行填充
36、 sort(value, reverse=False, case_sensitive=False, attribute=None)
{% for item in iterable|sort %} {% endfor %}
也可以通过指定属性参数属性排序(例如,按对象的日期排序)
{% for item in iterable|sort(attribute=‘date’) %} {% endfor %}
对可迭代进行排序。默认情况下,它会按升序排序,如果您将其作为第一个参数传递,它将反转排序。 如果iterable由字符串组成,则第三个参数可用于控制默认情况下禁用的比较的区分大小写。
37、 string(object)
接受一个对象, 转换成一个string字符串。如果尚未创建字符串unicode。这样,标记字符串不会转换回unicode。
38、 striptags(value)
剥离SGML / XML标记并将相邻的空格替换为一个空格
39、 sum(iterable, attribute=None, start=0)
返回数字序列的总和加上参数’start’的值(默认为0)。当序列为空时,它返回start。Total: {{ items|sum(attribute=‘price’) }}
40、 title(s)
返回值的标题版本。即单词将以大写字母开头,所有剩余字符均为小写
41、 tojsonvalueindent = None
将结构转储到JSON,以便在<script> 标签中使用是安全的它接受相同的参数并返回JSON字符串。请注意,这可以通过|tojson过滤器在模板中使用,这也会将结果标记为安全。由于此函数如何逃避某些字符,即使在<script>标记之外使用,这也是安全的
42、  trim(value)
去掉字符串开始和末尾多余的空白字符
43、 truncate(s, length=255, killwords=False, end=’…’, leeway=None)
{{ “foo bar baz qux”|truncate(9) }} -> “foo…”{{ “foo bar baz qux”|truncate(9, True) }} -> “foo ba…”{{ “foo bar baz qux”|truncate(11) }} -> “foo bar baz qux”{{ “foo bar baz qux”|truncate(11, False, ‘…’, 0) }} -> “foo bar…”
返回字符串的截断副本。使用默认的第一个参数指定长度255如果第二个参数是true过滤器将剪切文本的长度。否则它将丢弃最后一个字。如果文本实际上被截断,它将附加省略号(“…”)。如果您想要一个不同的省略号,“…”您可以使用第三个参数指定它。仅超过第四个参数中给出的容差范围的长度的字符串不会被截断。
44、 unique(value, case_sensitive=False, attribute=None)
{{ [‘foo’, ‘bar’, ‘foobar’, ‘FooBar’]|unique }} -> [‘foo’, ‘bar’, ‘foobar’]
返回给定iterable中的唯一项列表
参数:
case_sensitive – 将大写和小写字符串视为不同。
attribute – 过滤具有此属性的唯一值的对象。
45、 upper(s)
将值转换为大写
46、 urlencode(value)
转义字符串以在URL中使用(使用UTF-8编码)。它接受字典和常规字符串以及成对迭代。
47、  urlizevaluetrim_url_limit = Nonenofollow = Falsetarget = Nonerel = None
将纯文本URL转换为可单击的链接
48、 wordcount(s)
计算该字符串中的单词。
49、 wordwrapswidth = 79break_long_words = Truewrapstring = None
返回传递给79字符后包装的过滤器的字符串副本
50、 xmlattrdautospace = True
通过接受一个字典, 创建一个SGML/XML属性列表, 例如:
    <ul {{ {‘class’ = ‘my_list’, ‘missing’: none, ‘id’: ‘list’} | xmlattr }} />
     可以得到输出
    <ul class=’my_list’ id=’list’ />
     字典中指定的值为none的, 将不会被解析成标签属性.
内置测试列表
1、 callable(object)
返回对象是否可调用(即某种函数)
2、 defined(value)
{% if variable is defined %} value of variable: {{ variable }}{% else %} variable is not defined{% endif %}
如果定义了变量,则返回true:
3、 divisibleby(value, num)
检查变量是否可以被数字整除
4、 eq(a, b)
别名:    ==, equalto
5、 escaped(value)
检查值是否已转义
6、 even(value)
如果变量是偶数,则返回true
7、 geab 
别名:    >=
8、 gtab 
别名:    >, greaterthan
9、 in(value, seq)
检查值是否为seq
10、 iterable(value)
检查是否可以迭代对象
11、 le(a, b)
别名:    <=
12、 lower(value)
如果变量是小写的,则返回true
13、 lt(a, b)
别名:    <, lessthan
14、 mapping(value)
如果对象是映射(dict等),则返回true
15、 ne(a, b)
别名:    !=
16、 none(value)
如果变量为none,则返回true
17、 number(value)
如果变量是数字,则返回true。
18、 odd(value)
如果变量是奇数,则返回true
19、 sameas(value, other)
{% if foo.attribute is sameas false %} the foo attribute really is the `False` singleton{% endif %}
检查对象是否指向与另一个对象相同的内存地址:
20、 sequence(value)
如果变量是序列,则返回true。序列是可迭代的变量。
21、 string(value)
如果对象是字符串,则返回true。
22、 undefined(value)
如同defined()但反过来想。
23、 upper(value)
如果变量是大写的,则返回true。

扩展

下面的几节涵盖了可能被应用启用的 Jinja2 内置的扩展。应用也可以提供进一步 的扩展,但这不会在此描述。会有独立的文档来解释那种情况下的扩展。

i18n

如果启用来 i18n 扩展,可以把模板中的部分标记为可译的。标记一个段为可译的,可 以使用 trans:
<p>{% trans %}Hello {{ user }}!{% endtrans %}</p>
要翻译一个模板表达式——比如使用模板过滤器或访问对象的属性——你需要绑定表达式到 一个名称来在翻译块中使用:
<p>{% trans user=user.username %}Hello {{ user }}!{% endtrans %}</p>
如果你需要在 trans 标签中绑定一个以上的表达式,用逗号来分割( , ):
{% trans book_title=book.title, author=author.name %}
This is {{ book_title }} by {{ author }}{% endtrans %}
在翻译块中不允许使用语句,只能使用变量标签。
为表示复数,在 trans  endtrans 之间用 pluralize 标签同时指定单数和复 数形式:
{% trans count=list|length %}
There is {{ count }} {{ name }} object.
{% pluralize %}
There are {{ count }} {{ name }} objects.
{% endtrans %}
默认情况下块中的第一个变量用于决定使用单数还是复数。如果这不奏效,你可以指定 用于复数的名称作为 pluralize 的参数:
{% trans …, user_count=users|length %}
{% pluralize user_count %}{% endtrans %}
也可以翻译表达式中的字符串。为此,有三个函数:
_ gettext: 翻译一个单数字符串 – ngettext: 翻译一个复数字符串 – _: gettext 的别名
例如你可以容易地这样打印一个已翻译的字符串:
{{ _(‘Hello World!’) }}
你可以使用 format 过滤器来使用占位符:
{{ _(‘Hello %(user)s!’)|format(user=user.username) }}
因为其它语言可能不会用同样的顺序使用词汇,要使用多个占位符,应始终用字符 串参数传给 format 
Changed in version 2.5.
如果激活了新样式的 gettext 调用( 新样式 Gettext ),使用占位符 会更加简单:
{{ gettext(‘Hello World!’) }}{{ gettext(‘Hello %(name)s!’, name=‘World’) }}{{ ngettext(‘%(num)d apple’, ‘%(num)d apples’, apples|count) }}
注意 ngettext 函数的格式化字符串自动接受 num 参数作为计数作为附加的 常规参数。

表达式语句

如果加载了表达式语句扩展,一个名为 do 的扩展即可用。它工作几乎如同常规的变量 表达式( {{  }} ),只是它不打印任何东西。这可以用于修改列表:
{% do navigation.append(‘a string’) %}

循环控制

如果应用启用来 循环控制 ,则可以在循环中使用 break  continue 。到达 break 时,循环终止。到达 continue 时,当前处理会终止并 从下一次迭代继续。
这个循环每两项跳过一次:
{% for user in users %}
{%if loop.index is even %}{% continue %}{% endif %}
{% endfor %}
同样,这个循环 10 次迭代之后会终止处理:
{% for user in users %}
{%if loop.index >= 10 %}{% break %}{% endif %}{%endfor %}

With 语句

New in version 2.3.
如果应用启用了 With 语句 ,将允许在模板中使用 with 关键 字。这使得创建一个新的内作用域。这个作用域中的变量在外部是不可见的。
With 用法简介:
{% with %}
{% set foo = 42 %}
{{ foo }} foo is 42 here
{% endwith %}
foo is not visible here any longer
因为在作用域的开始设置变量很常见,你可以在 with 语句里这么做。下面的两 个例子是等价的:
{% with foo = 42 %}
{{ foo }}{% endwith %}
{% with %}
{% set foo = 42 %}
{{ foo }}{% endwith %}

自动转义扩展

New in version 2.4.
如果你的应用程序设置了 自动转义扩展 ,你就可以在模版中开启或者关闭自动转义。
例子:
{% autoescape true %}
自动转义在这块文本中是开启的。
{% endautoescape %}
{% autoescape false %}
自动转义在这块文本中是关闭的。
{% endautoescape %}
 endautoescape 标签之后,自动转义的行为将回到与之前相同的状态。

 

打赏

未经允许不得转载:同乐学堂 » Flask入门到精通-Day3

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

特别的技术,给特别的你!

联系QQ:1071235258QQ群:226134712
error: Sorry,暂时内容不可复制!