侧边栏壁纸
  • 累计撰写 218 篇文章
  • 累计创建 59 个标签
  • 累计收到 5 条评论

Jinja2 模板设计者文档

barwe
2021-09-26 / 0 评论 / 0 点赞 / 770 阅读 / 4,767 字
温馨提示:
本文最后更新于 2022-07-14,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

模板设计者文档

模板是文本文件,对于Jinja引擎来说,并不区分文本文件的扩展名。

Jinja模板的语法与Django和Python十分相似,主要包括遍历、表达式和标签等几类。

中文文档:http://www.ainoob.cn/docs/jinja2/templates.html

变量

{{ name }}
{{ student.name }}
{{ student['name'] }}

变量被替换成什么内容,完全取决于程序提供什么内容。如果变量未被定义,默认打印空字符串。

Jinja处理student.namestudent['name']的方式有所差别:

  • .name优先检查student对象的属性,然后检查其项,都没查找到时返回未定义对象
  • ['name']优先检查student对象的项,然后检查其属性,都没查找到时返回未定义对象
  • 如果一个对象具有同名但不同值的属性和项,这个差异就非常重要
  • attr()过滤器只查找属性

过滤器

过滤器实际上就是一类特殊的函数。该函数以Jinja变量作为第一参数,返回一个新的值用于模板填充。
因此可以用管道符|来表示过滤器“修改”变量并填充新值的这一行为。
管道符可以串联多个过滤器,使用最后的结果填充模板。

{{ name|stringtags|title }}
{{ list|join(', ') }}

内置过滤器清单:http://www.ainoob.cn/docs/jinja2/templates.html#builtin-filters

  • abs(number)
  • attr(object, name):类似于object.name,但是只查找对象的属性
  • batch(value, linecount, fill_with=None):对序列进行分批
  • capitalize(string):大写首字母,小写其他所有字母
  • center(value, width=80):将值居中
  • default(value, default='', boolean=false):为未定义的变量提供默认值,简写为d
  • dictsort(_dict, case_sensitive=false, by='key')对字典进行排序
  • escape(string):转义HTML中的特殊字符,例如&, <, >, ', "
  • filesizeformat(value, binary=false):文件大小数值的可视化
  • first(seq)
  • float(value, default=0.0)
  • forceescape(value)
  • format(value, *args, **kwargs):与Python的format函数相似
  • groupby(objects, attribute):将对象序列按照指定属性分组
  • indent(s, width=4, indentfirst=false):每一行缩进指定宽度,首行默认不缩进
  • int(value, default=0, base=10)
  • join(seq, sep='', attribute=none)
  • last(seq)
  • length(seq_or_map)
  • list(value)
  • lower(s)
  • map(seq, other_filter) or map(mapping, attribute)
  • pprint(value, verbose=false):友好的打印
  • random(seq):采样
  • reject(objects, test):测试
  • rejectattr(objects, attr, value?)
  • replace(s, old, new, count=none)
  • reverse(value)
  • round(value, precision=0, method='common'):四舍五入
  • safe(value):在自动转义的环境中不进行转义
  • select(objects, test):选择
  • selectattr(objects, attr, value?)
  • slice(iterator, slices, fill_with=none)
  • sort(iterable, reverse=false, case_sensitive=false, attribute=none)
  • string(object)
  • striptags(value):移除SGML/XML中的标签,并将相邻的空白改为一个空格
  • sum(iterable, attribute=none, start=0)
  • title(s)
  • trim(s):移除首位的空白
  • truncate(s, length=255, killwords=false, end='...'):截取字符串
  • uper(s)
  • urlencode(value)
  • urlize(value, trim_url_limit=none, nofollow=false, target=none):可点击的文本
  • wordcount(s):数单词
  • wordwrap(s, ...) ???
  • xmlattr(...) ???

测试

测试即检测某个值是否符合某个条件,实际上就是条件判断。
测试是一种语句,通过关键字is进行,例如{% loop.index is divisibleby(3) %}

内置测试清单:http://www.ainoob.cn/docs/jinja2/templates.html#builtin-tests

  • callable 对象是否可以被调用,例如函数、类
  • defined or undefined 是否被定义
  • divisibleby 是否能作为分母
  • equalto(value, other) 是否相等
  • escaped 是否被转义
  • odd or even 奇偶
  • iterable 是否可迭代
  • upper or lower 大小写
  • mapping 是否是字典
  • none 是否为空
  • number 数值
  • sameas(object, other) 是否指向同一内存地址
  • sequence 序列
  • string 字符串

注释

{#
	This is a comment.
#}

空白控制

默认情况下,模板引擎不会修改块中的空白(空格、制表符、换行符等)

……

转义

……

行语句

……

模板继承

在父模板中定义骨架,包括多个可被子模板覆盖的块。

……

HTML转义

……

控制

包括条件判断、循环、宏、块等。控制流的语法是{% ... %}

for

遍历数组:

<ul>
{% for user in users %}
	<li>{{ user.name|e }}</li>
{% endfor %}
</ul>

遍历字典:

<dl>
{% for key, value in some_dict.iteritems() %}
	<dt>{{ key|e }}</dt>
	<dd>{{ value|e }}</dd>
{% endfor %}
</dl>

for循环中的特殊变量:

  • loop.index:当前循环迭代的次数,从1开始
  • loop.index0:当前循环迭代的次数,从0开始
  • loop.revindex:到循环结束还需要迭代的次数,从1开始
  • loop.revindex0:到循环结束还需要迭代的次数,从0开始
  • loop.first:是否是第一次迭代
  • loop.last:是否是最后一次迭代
  • loop.length:迭代的总次数
  • loop.cycle:辅助函数

loop.cycle辅助函数

……

for ... if ...跳过循环

没有break或者continue语句跳出循环。作为替代,可以使用条件来跳过迭代:

{% for user in users if not user.hidden %}
	<li>{{ user.name }}</li>
{% endfor %}

跳过的迭代不会计入循环的特殊变量中。

for ... else ...

如果没有进行有效的迭代,例如迭代序列为空,或者所有条目都被过滤掉了,就会执行else中的块:

<ul>
{% for user in users %}
	<li>{{ user.name }}</li>
{% else %}
	<li>no user found!</li>
{% endfor %}
</ul>

递归地使用循环

……

if

{% if kenny.sick %}
    Kenny is sick.
{% elif kenny.dead %}
    You killed Kenny!  You bastard!!!
{% else %}
    Kenny looks okay --- so far
{% endif %}

If 也可以被用作 内联表达式 并作为 循环过滤

……

调用

……

过滤器

{% filter upper %}
    This text becomes uppercase
{% endfilter %}

赋值

{% set navigation = [('index.html', 'Index'), ('about.html', 'About')] %}
{% set key, value = call_something() %}

继承

……

……

包含

……

导入

……

导入上下文行为

……

表达式

字面量

  • "barwe" or 'barwe'
  • 12 or 12.3
  • ["apple", "banana", "orange"]
  • (1,) or (1, 2, 3)
  • {"key": "value"}
  • true or false
  • none

算术

+, -, *, /, //, %, **

比较

==, !=, >, >=, <, <=

逻辑

and, or, not

isinnot搭配时需要使用中缀记法:is not, not in

其他运算符

  • in or not in:左边是否包含于右边

  • is or is not:左边是否等于右边

  • |:应用一个过滤器

  • ~:将所有操作数转换为字符串并连接它们,例如

    {% set name = "barwe" %}
    {% set age = 26 %}
    {{ "The age of " ~ name ~ " is " ~ age }}
    {# The age of barwe is 26 #}
    
  • ():调用宏、过滤器等

  • . or []:获取对象的属性或者项

if表达式

内联的if表达式与Python相似:

{% extends layout_template if layout_template is defined else 'master.html' %}

不同的是,Python需要同时指定ifelse,Jinja2可以不用指定else,此时返回一个未定义对象。

全局函数清单

  • range(stop)
    range(start, stop)
    range(start, stop, step)
    整数列表
  • lipsum(n=5, html=true, min=20, max=100) ???
  • dict(**items) 字典字面量
  • class cycler(*items) 周期,更像是生成器,但是可以回退
    • .reset() 重置到第一个
    • .next() 返回当前项并跳转到下一个
    • .current 返回当前项
  • class joiner(sep=',') ???

扩展

i18n

……

表达式语句

加载表达式语句扩展,使用不打印的表达式:

{% do some_seq.append('something') %}

循环控制

启用 break 和 continue:

{% for user in users %}
	{% if loop.index is even %}
		{% continue %}
	{% endif %}
{% endfor %}

with语句

设置一个内作用域,该作用域内定义的变量对作用域外不可见:

{% with %}
	{% set name = "barwe" %}
	{{ name }} name is "barwe"
{% endwith %}

自动转义

{% autoescape true %}
...
{% endautoescape %}
0

评论区