Jinja2

  Jinja2是Python Web编程中的主流模板语言。因为flask是基于Jinja2和Werkzeug发展而来,在安装flask的时候jinja2自动就被装在上面了。

  之前提到了很多Jinja2的使用方法啊,下面将补充或者更加详细地说明Jinja2作为模板语言的使用。

  【Jinja2官方文档】http://docs.jinkan.org/docs/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的值。说了一串自己都晕了,下面给个例子。。

  比如模板是这个样子的:

    <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>

  而作为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"})

  那么最终得到渲染完成的文件是长这个样子的:

<ul>
<li>female
<ul>
<li>Bob Kazuya</li>
<li>Ocean King</li>
</ul>
</li>
<li>male
<ul>
<li>Frank Takanashi</li>
</ul>
</li>
</ul>

  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表示小数点后保留几位。method除了common是四舍五入规则外,floor是向下抹平,ceil是向上抹平。

  * 今天遇到了round的一个坑,就是需要注意round前面的东西一定要是一个整体。当然1.23|round之类,直接写数字没问题,当使用算式时请注意一定要把算式用括号括起来才能使过滤器有效。比如 num/1024.0 | round是不会有四舍五入之类的效果的,只有(num/1024.0) | round才行。

  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整除的话就进入这个逻辑分支

  除了上面这些带参数的判断条件,也有一些不带参数的条件,在Jinja2里被称为测试器(test)。比如:

  defined/none  检查一个对象是否被定义,其实效果和{% if var %}是一样的

  upper/lower  检查一个字符串对象是否都是大写或小写

  string  {% if var is string %}检查对象是不是一个字符串

  odd/even  检查一个整数对象是否是奇/偶数

  iterable  检查一个对象是不是可迭代对象,简单来说就是看是不是列表之类的序列类型

  mapping  检查一个对象是不是k-v对形式的对象,比如字典

  ●  自定义测试器

  如果内置的一些测试器不能满足我们的需求,那么我们可以自定义一些测试器。具体的做法是在python代码中写一个测试函数,然后用app.add_template_test方法把这个测试器和app对象关联起来。比如下面这个:

def over_five(string):
#接受的一定是一个字符串对象,然后可以在函数中对这个字符串做出处理
return int(string) > 5 app.add_template_test(over_five,'my_test') '''
然后在模板中就可以这么用了:
{% if num is my_test %}
<p>{{ num }} is bigger than 5</p>
{% else %}
<p>{{ num }} is smaller than 5</p>
{% endif %}
'''

  

  ●  判断语句

  判断语句没什么好说的了,反正就是{% 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 %}
<li>
   {% if not loop.first %}
{{ user.username }}
{% endif %}
</li>
{% endfor %}

  就是说假如是循环中的第一个,就不显示它的username了。

■  模板继承

  之前在简介中也说过好多次,jinja2的模板是可以进行继承的。采用关键字{% extends "parent.html" %}的形式。

  父模板中可以有多个不重名的{% block xxx %}{% endblock %},在子模板中通过{% block xxx %}可以指定修改某个block中的内容。更加详尽的内容都写在flask的大概介绍里,就不重复了。

■  独立使用jinja2

  jinja2作为一个插件很广泛地用于flask,django等框架中。但是也不能忘记,jinja2本身就是一个python的模块。在非框架的环境中,我们也可以通过其API单独进行jinja2的调用。常用的方法是这样子的:

from jinja2 import Template

t = Template('Hello, {{ name }}')
print t.render(name='Frank')
# 输出 Hello, Frank

  可以看到,通过给Template类传递一段模板代码,然后调用其render方法,并且给出模板中变量的定义,就可以得到渲染出来的代码了。但是这样有一点不好就是要把模板内容全部写出来,最好是有传递文件名来指定一个模板的。这就要用到jinja2中的Envrionment和Loader两个概念:

from django import Environment,FileSystemLoader

env = Environment(loader=FileSystemLoader('/path/to/directory'))
t = env.get_template('test.html') print t.render(name='Frank')
# 将模板文件test.html按照给出的参数进行渲染

  /path/to/directory是test.html所在的目录,该目录下所有其他文件也可以通过get_template方法来作为一个模板文件获取出来。这里直接写模板文件名说明模板文件就在目录下,如果有多层级目录也可以写/path/to/file.html。FileSystemLoader应该是一个常用的Loader,它将某个指定的目录作为模板的存放目录加入环境中。除了FileSystemLoader以外,还有其他的一些Loader比如PackageLoader,PackageLoader('application','templates')将包application(中有__init__.py文件)中的templates目录作为模板的存放目录。

  模板内容渲染成实际代码的逻辑和过程和框架中的jinja2是一样的。

  

【Flask】 Jinja2模板语言的更多相关文章

  1. 第四篇flask中模板语言 jinja2

    Flask中默认的模板语言是Jinja2 首先我们要在后端定义几个字符串,用于传递到前端 STUDENT = {, 'gender': '中'}, STUDENT_LIST = [ {, 'gende ...

  2. flask 基本操作 模板语言 session

    Django web:优点:大而全,ORM models ,model Form ,admin ,csrf ,session缺点:资源浪费 Flask web:优点:小而精,ORM:x , Form: ...

  3. flask之jinja2模板语言

    一.jinja2简单介绍 Jinja2是Python里一个被广泛应用的模版引擎,他的设计思想来源于Django的模板引擎,并扩展了其语法和一系列强大的功能.其中最显著的一个是增加了沙箱执行功能和可选的 ...

  4. Python Flask Jinja2模板引擎

    模板 简介 模板是一个包含响应文本的文件,其中包含用占位变量表示的动态部分,其具体值只在请 求的上下文中才能知道. 渲染 使用真实值替换变量,再返回最终得到的响应字符串,这一过程 称为渲染.为了渲染模 ...

  5. [Flask]jinja2模板-宏的使用

    定义宏: macros.html <!DOCTYPE html> <html lang="en"> <head> <meta charse ...

  6. Flask最强攻略 - 跟DragonFire学Flask - 第四篇 Flask 中的模板语言 Jinja2 及 render_template 的深度用法

    是时候开始写个前端了,Flask中默认的模板语言是Jinja2 现在我们来一步一步的学习一下 Jinja2 捎带手把 render_template 中留下的疑问解决一下 首先我们要在后端定义几个字符 ...

  7. python 全栈开发,Day119(Flask初识,Render Redirect HttpResponse,request,模板语言 Jinja2,用户登录例子,内置Session)

    一.Flask初识 首先,要看你学没学过Django 如果学过Django 的同学,请从头看到尾,如果没有学过Django的同学,并且不想学习Django的同学,轻饶过第一部分 三大主流Web框架对比 ...

  8. 第四篇 Flask 中的模板语言 Jinja2 及 render_template 的深度用法

    是时候开始写个前端了,Flask中默认的模板语言是Jinja2 现在我们来一步一步的学习一下 Jinja2 捎带手把 render_template 中留下的疑问解决一下 首先我们要在后端定义几个字符 ...

  9. 3,Flask 中的模板语言 Jinja2 及 render_template 的深度用法

    Flask中默认的模板语言是Jinja2 现在我们来一步一步的学习一下 Jinja2 捎带手把 render_template 中留下的疑问解决一下 首先我们要在后端定义几个字符串,用于传递到前端 S ...

随机推荐

  1. 你的变量究竟存储在什么地方 && 全局内存

    我相信大家都有过这样的经历,在面试过程中,考官通常会给你一道题目,然后问你某个变量存储在什么地方,在内存中是如何存储的等等一系列问题.不仅仅是在面试中,学校里面的考试也会碰到同样的问题.  如果你还不 ...

  2. com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxError Exception

    1.错误描述 com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxError Exception:You have an error in your SQL synt ...

  3. spoj freetour II

    昨天吐槽还没A,今天就A了 有个变量开成了全局变量,应该携程局部变量 对于中间的solve我也不懂为什么是nlog2n,我不看题解也不会做 #include<bits/stdc++.h> ...

  4. 异常-----freemarker.template.TemplateException

    一,案例一 1.1.错误描述 五月 30, 2014 11:33:57 下午 freemarker.log.JDK14LoggerFactory$JDK14Logger error 严重: Templ ...

  5. 小例子理解SQL的左连接与右连接

    假设有A,B两个表. 表A记录如下: aID aNum a20050111 a20050112 a20050113 a20050114 a20050115 表B记录如下: bID bName ---- ...

  6. 简述Spring事务有几种管理方法,写出一种配置方式

    Spring事务有两种方式: 1.编程式事务:(代码中嵌入) 2.声明式事务:(注解,XML) 注解方式配置事务的方式如下: 首先,需要在applicationContext.xml中添加启动配置,代 ...

  7. 【BZOJ4012】开店(主席树)

    [BZOJ4012]开店(主席树) 题面 Description 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱 ...

  8. 【BZOJ1834】网络扩容(最大流,费用流)

    [BZOJ1834]网络扩容(最大流,费用流) 题面 Description 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用.求: 1. 在不扩容的情况下 ...

  9. 【Luogu2711】小行星(网络流,最大流)

    [Luogu2711]小行星(网络流,最大流) 题面 题目描述 星云中有n颗行星,每颗行星的位置是(x,y,z).每次可以消除一个面(即x,y或z坐标相等)的行星,但是由于时间有限,求消除这些行星的最 ...

  10. STM32高级定时器TIM1产生两路互补的PWM波(带死区)

    测试环境:Keil 5.20.0.0 STM32F103RBT6 固件库版本:STM32F10x_StdPeriph_Lib_V3.5.0(2011) 本文使用TIM1的通道1,通道2,产生两路1kh ...