Jinja2
Jinja2是Python Web编程中的主流模板语言。因为flask是基于Jinja2和Werkzeug发展而来,在安装flask的时候jinja2自动就被装在上面了。
之前提到了很多Jinja2的使用方法啊,下面将补充或者更加详细地说明Jinja2作为模板语言的使用。
【Jinja2官方文档】
■ 基本语义
看过之前模板的例子就知道,Jinja2做构成的模板文件中,文本内容大致可以分成几个种类。比如特殊文本(不进行转义,比如HTML,XML格式的文本)、{
{ }}表示的变量或者宏调用、{% %}表示逻辑控制,{# #}表示注释,其中内容不被模板引擎转义。
■ set语句赋值
在之前的所有例子中,模板中变量的值似乎只有一个来源,就是来自于后端的提供。但是实际上我们可以在模板这个层面对变量进行赋值,就是通过了{% set variable_name="value" %}的形式。这赋予了模板在内部进行变量赋值的能力,提高了灵活性。如果想要set一个变量的值为某个函数的返回值的话,那么那个函数不用{
{ }}包着。比如{% set action_view = url_for('main.upload') %}而不是{ { url_for('main.upload') }}。
■ 过滤器
Jinja2可以使用过滤器,对传入模板的第一手数据进行二次加工。过滤器的形式是以管道符号连接第一手数据和二次处理数据的方法。比如在模板中写:
{ { my_variable|default("my_variable is not defined") }}
的意思就是说在此处的第一手数据是由后端传过来的my_variable这个变量的值。如果这个变量没有被定义,那么就有default过滤器方法指定了它没有被定义时应该显示什么东西。过滤器方法有很多很多,各种各样的过滤器方法使得数据从后端传入前段之后还能再进行灵活的操作,从而提高了整个编程的便利性和敏捷性。其他常用或者我看着比较有用的过滤器方法还有:
****以下说明中的第一个参数都是指通过管道传过去的值,实际写在管道右边的方法参数应该比下面说明中的少一个,就像python面向对象编程中的self参数那样的感觉****
attr(object,name) 比如account|attr("name")中account预期是一个字典(或者按照JS的说法是一个object),此时这个地方就是现实account['name']的值
capitalize(s) 把字符串的首字母大写,后面的全部小写
default(value,default_value=u'',boolean=False) 设置默认值,如果没有给出value,那么就用default_value的值(即空字符串)
filesizeformat(value,binary=False) 接受一个数值然后转化成容易阅读的字节形式比如1.3MB,305Byte等,比如{
{ size|filesizeformat() }}float(value,default=0) 接受一个值并将其转化为float类型
escape(string) 把字符串中HTML特殊字符比如<,>,&等反转义成HTML的表达方式
groupby(value,attribute) 按照指定的共有属性将(一个字典组成的列表)集合进行分组,返回一个字典组成的列表。这个列表中的每个字典都有两项,第一项的key是grouper然后value是根据groupby区分后得到的那个原字典中key的值。说了一串自己都晕了,下面给个例子。。
比如模板是这个样子的:
- {% for group in persons|groupby('gender') %}
- { { group.grouper }}
- {% for person in group.list %}
- { { person.first_name }} { { person.last_name }} {% endfor %}
{% endfor %}
而作为persons传入的数据lst是这个样子的:
lst = [] lst.append({"gender":"male","first_name":"Frank","last_name":"Takanashi"}) lst.append({"gender":"female","first_name":"Bob","last_name":"Kazuya"}) lst.append({"gender":"female","first_name":"Ocean","last_name":"King"})
那么最终得到渲染完成的文件是长这个样子的:
- female
- Bob Kazuya
- Ocean King
- male
- Frank Takanashi
int(value,default) 把值转化为一个int类型
join(value,sep=u'') 接受一个序列类型的对象,然后通过sep指定的字符将所有序列元素连接在一起成为一个字符串。sep默认是空字符串
last/first/random(seq) 返回序列的最后/最前/随机一个元素
replace(string,old,new,count=None) 接受一个字符串,将其中的old部分全部转化为new,从左到右替换count次,如果不指定count是只替换第一个扫描到的
reverse(value) 接受一个可迭代对象,然后返回其反序序列的迭代器
sort(value,reverse=False,case_sensative=False,attribute=None) 对可迭代的对象进行排序,默认情况下以升序大小写不敏感的方式排序。
striptags(value) 把一段比如XML格式的文本中的标签都去掉
sum(iterable,attribute=None,start=0) 对可迭代对象进行求和,如果需要对其某个特定属性的值求和的话可以设置attribute属性
title(string) 将字符串转换为标题格式显示
trim(value) 去除开头和末尾的所有空格,相当于strip()
truncate(s,length=255,killwords=False,end='...') 这是个比较有有意思的方法,它把字符串转化成简略形式,比如"foo bar"|truncate(5)可以得到foo ...,如果"foo bar"|truncate(5,True)可以得到foo b...
round(value,precision=0,method='common') 对数字进行四舍五入,precision表示小数点后保留几位。
wordcount(s) 计算字符串中单词的个数
以上还不是过滤器方法的全部,一般而言这些处理都可以放在python中做,python也可以做的非常好,但是这样的话势必要往模板中传递很多很多变量。如果可以在模板这个层面对这些数据进行一些二次处理的话就可以让后端和前端之间的交互体量变小,提高编程的便利性。
■ 逻辑结构
Jinja2中和一般编程语言中一样,可以有if/else,for,is等等关键字作为逻辑控制的节点。而这些关键字必须是放在{% %}或者{
{ }}里面的。● is关键字判断条件
利用is关键字和所谓的“测试方法”可以获得一个布尔值,从而利用其进行一些逻辑判断。比如{
{ name is defined }}可以返回True/False来体现name这个变量是否被定义了。类似的“测试方法”还有:callable(object) 检查一个对象是否可调用
defined/undefined(object) 检查一个对象是/否被定义了
divisibleby(value,num) 检查value能否被数字num整除
escaped(value) 检查一个对象是否被转码了
iterable(value) 检查一个对象是否可迭代
lower/upper(value) 检查一个对象是否都小/大写
none(value) 检查一个对象是否是None
number(value) 检查一个对象是否是数字
sameas(value,other) 检查一个对象是否和other这个对象是同一个对象
用法:{% if loop.index is divisibleby(3) %}就表示如果loop.index这个值能够被3整除的话就进入这个逻辑分支
● 判断语句
判断语句没什么好说的了,反正就是{% if ... %}{% elif ... %}{% else %}{% endif %}的格式。
● 循环语句
Jinja2中的循环只能通过for语句,而且不具备break,continue之类的循环控制功能。但是在for循环的作用域内,可以访问特殊对象loop的一些属性来获得循环的一些信息。loop具有以下属性:
loop.index 当前循环迭代的次数(从1开始计数)
loop.index0 从0开始计数的循环迭代次数
loop.revindex 到循环结束为止需要迭代的次数
loop.first 是否是第一次迭代
loop.last 是否是最后一次迭代
loop.length 序列中项目的数量
loop.cycle 在一串序列间取值的辅助函数
比如下面这个代码的用例:
{% for user in users %}
就是说假如是循环中的第一个,就不显示它的username了。
■ 模板继承
之前在简介中也说过好多次,jinja2的模板是可以进行继承的。采用关键字{% extends "parent.html" %}的形式。
父模板中可以有多个不重名的{% block xxx %}{% endblock %},在子模板中通过{% block xxx %}可以指定修改某个block中的内容。更加详尽的内容都写在flask的大概介绍里,就不重复了。