Jinja教程(转)

介绍

Jinja是基于python的模板引擎,功能比较类似于于PHP的smarty,J2ee的Freemarker和velocity。

运行需求

Jinja2需要Python2.4以上的版本。

安装

按照Jinja有多种方式,你可以根据需要选择不同的按照方式。

使用easy_install安装

使用easy_install 或pip:

#sudo easy_install Jinja2

#sudo pip install Jinja2

这两个工具可以自动从网站上下载Jinja,并安装到python目录的site-packages目录中。

从tar包安装

# 下载Jinja的安装包

# 解压缩

# sudo python setup.py install

基本API用法

用Jinja创建模板最简单的方式是通过 Template. 但在实际应用中并不推荐此用法:

 

>>> from Jinja2 import Template

>>> template = Template('Hello {{ name }}!')

>>> template.render(name='World')

u'Hello World!'

这个例子使用字符串作为模板内容创建了一个Template实例,然后用"name='World'"作为参数调用"render方法,将内容中 的'name'替换为"World",最终返回渲染过的字符串--"u'Hello World!'"。

API

Environment

Environment是Jinja2中的一个核心类,它的实例用来保存配置、全局对象,以及从本地文件系统或其它位置加载模板。

多数应用会在初始化时创建Environment实例,然后用它来加载模板。当然,如果系统有必要使用不同的配置,也可以创建多个 Environment实例一起使用。

配置Jinja2为你的应用加载模板的最简单的方式可以像下面这样:

from Jinja2 import Environment, PackageLoader

env = Environment(loader=PackageLoader('yourapplication', 'templates'))

上述代码使用缺省配置创建了一个Environment实例,并指定PackageLoader作为模板加载器。PackageLoader可以 从你的python应用程序的包中读取并加载模板。在之后的文档中会逐一介绍Jinja2的加载器。

创建了Environment实例,我们就可以加载模板了:

template = env.get_template('mytemplate.html')

之后就可以跟上文中的例子一样用render方法来渲染模板了。

print template.render(the='variables', go='here')

高级API

Environment类:

class Environment(block_start_string='{%', block_end_string='%}', variable_start_string='{{', vari-

able_end_string='}}', comment_start_string='{#', comment_end_string='#}',

line_statement_preix=None, trim_blocks=False, extensions=(), optimized=True,

undefined=, finalize=None, autoescape=False,

loader=None)

Environment是Jinja2的核心组件,它包含了重要的共享变量,例如:配置,过滤器,测试器,全局变量等等。Environment 的实例如果没有被共享或者没有加载过模板则可以进行修改,如果在加载过模板之后修改Environment实例会遇到不可知的结果。

参数介绍:

loader 模板加载器.

block_start_string 块开始标记符,缺省是 '{%'.

block_end_string 块结束标记符,缺省是 '%}'.

variable_start_string 变量开始标记符,缺省是 '{{'.

variable_start_string 变量结束标记符,缺省是 '{{'.

comment_start_string 注释开始标记符,缺省是 '{#'.

comment_end_string 注释结束标记符,缺省是 '#}'.

通过修改上面几个标记符参数,可以让我们的模板变成另外一种风格,比如

env = Environment(

block_start_string="<#", block_end_string="#>,

variable_start_string="${", variable_start_string="}",

comment_start_string="<#--", comment_end_string="--#>", ...)

这样,我们的模板可以设计为下面的样子:

<# block title #> Index <# endblock #>

${name}

<#-- this is comment --#>

怎么样,是不是有点像freemarker的风格?但是我们不推荐这样做,否则就无法使用Jinja的编辑器来编辑模板了。

auto_reload

如果设为True,Jinja会在使用Template时检查模板文件的状态,如果模板有修改, 则重新加载模板。如果对性能要求较高,可以将此值设为False。

autoescape XML/HTML自动转义,缺省为false. 就是在渲染模板时自动把变量中的<>&等字符转换为<>&。

cache_size

缓存大小,缺省为50,即如果加载超过50个模板,那么则保留最近使用过多50个模板,其它会被删除。如果换成大小设为0,那么所有模板都会在使用时被重 编译。如果不希望清除缓存,可以将此值设为-1.

undefined Undefined或者其子类,用来表现模板中未定义的值

使用过freemarker的朋友应该知道,在freemarker中模板中使用值为null的变量时会看到一个“很黄很暴力”的一堆错误栈信息。有些人 对freemarker的这种处理方式不以为然,因为这样还需要对变量值加入判断,处理起来比较繁琐。而另一个比较有名气的模板引擎Velocity则会 忽略空值,例如在Velocity中打印值为null的变量将会得到一个空字符。

Jinja通过设置不同的undefined参数来得到类似Freemarker或者Velocity的处理方式。

line_statement_prefix 指定行级语句的前缀.

extensions Jinja的扩展的列表,可以为导入到路径字符串或者表达式类

Template类

Template类是Jinja的另一个重要的组件,它可以被看作是一个编译过的模板文件,被用来产生目标文本.

Template类的构建器参数和Environment类基本相同, 区别是,创建Template实例需要一个模板文本参数,另外它不需要loader参数。

Template实例是一个不可变对象,即你不能修改Template实例的属性。

一般情况下,我们会使用Environment实例来创建Template,但也可以直接使用Template构建器来创建。如果要用构建器来创 建Template实例,那么Jinja会根据构建器参数自动为此Template创建/指派一个内部Environment实例,凡是使用相同构建器参 数(不包括模板文本串参数)创建的Template实例都会共享同一个内部Environment实例。

方法:

render(*args, **kwargs)

此方法接受与“dict”相同的构建器参数:一个dict,dict的子类,或者一些关键字参数。下面两种调用方式是等价的:

template.render(knights='that say nih')

template.render({'knights': 'that say nih'})

generate(*args, **kwargs)

此方法会一段一段的渲染模板,而不是一次性的将整个模板渲染成目标文本。这对产生非常大的模板时非常有用。调用此方法会返回一个产生器 (generator),它可以....

stream(*args, **kwargs)

与generate功能类似,只不过此方法返回一个TemplateStream module

此方法用来在模板运行时导入, 也可以用来在python代码中访问导出的模板变量.

>>> t = Template('{% macro foo() %}42{% endmacro %}23')

>>> unicode(t.module)

u'23'

>>> t.module.foo()

u'42'.

Undefined Types 未定义类型

Undefined及其子类类被用来作为未定义类型。Environment的构建器可以指定undefined参数,它可以是undefined types中的任意一个,或者是Undefined的子类。当模板引擎无法找到一个名称或者一个属性时,使用的Undefined会决定哪些操作可以正常 进行,哪些不可以。

'''class Undefined(hint=None, obj=None, name=None)'''

缺省undefined类型。此未定义类型可以打印或者作为sequence迭代。但是不能做其它操作,否则会抛出UndefinedError

 

foo = Undefined(name='foo')

>>> str(foo)

''

>>> not foo

True

>>> foo + 42

Traceback (most recent call last):

...

Jinja2.exceptions.UndefinedError: 'foo' is undefined

'''class DebugUndefined(hint=None, obj=None, name=None)'''

 

>>> foo = DebugUndefined(name='foo')

>>> str(foo)

'{{ foo }}'

>>> not foo

True

>>> foo + 42

Traceback (most recent call last):

...

Jinja2.exceptions.UndefinedError: 'foo' is undefined

'''class StrictUndefined(hint=None, obj=None, name=None)'''

 

>>> foo = StrictUndefined(name='foo')

>>> str(foo)

Traceback (most recent call last):

...

Jinja2.exceptions.UndefinedError: 'foo' is undefined

>>> not foo

Traceback (most recent call last):

...

Jinja2.exceptions.UndefinedError: 'foo' is undefined

>>> foo + 42

Traceback (most recent call last):

...

Jinja2.exceptions.UndefinedError: 'foo' is undefined

Loaders 加载器

加载器负责从某些位置(比如本地文件系统)中加载模板,并维护在内存中的被编译过的模块。

文件系统加载器,它可以从本地文件系统中查找并加载模板:

class FileSystemLoader(searchpath, encoding='utf-8', cache_size=50, auto_reload=True)

第一个参数searchpath是查找路径,它可以是一个路径字符串,也可以是保护多个路径的sequence。

 >>> loader = FileSystemLoader('/path/to/templates')

>>> loader = FileSystemLoader(['/path/to/templates', '/other/path'])

包加载器。它可以从python包中加载模板:

class PackageLoader(package_name, package_path='templates', encoding='utf-8', cache_size=50, auto_reload=True)

>>> loader = PackageLoader('mypackage', 'views')

字典加载器。在mapping参数中明确指定模板文件名的路径。它用来做单元测试比较有用:

class DictLoader(mapping, cache_size=50, auto_reload=False)

>>> loader = DictLoader({'index.html': 'source here'})

函数加载器。让指定的函数来返回模板文件的路径。

class FunctionLoader(load_func, cache_size=50, auto_reload=True)

>>> def load_template(name):

... if name == 'index.html'

... return '...'

...

>>> loader = FunctionLoader(load_template)

前缀加载。如果你的工程中包含很多应用,那么多应用之间模板名称就可能存在命名冲突的问题。使用前缀加载器可以有效的解决不同应用之间模板命名冲 突问题。

class PrefixLoader(mapping, delimiter='/', cache_size=50, auto_reload=True)

 >>> loader = PrefixLoader({

... 'app1': PackageLoader('mypackage.app1'),

... 'app2': PackageLoader('mypackage.app2')

... })

如此,如果要使用app1中的模板,可以get_template('app1/xxx.html'), 使用app2的模板,可以使用get_template('app2/xxx.html')。delimiter字符决定前缀和模板名称之间的分隔符,默 认为'/'。

选择加载器,与PrefixLoader类似,可以组合多个加载器。当它在一个子加载器中查找不到模板时,它会在下一个子加载器中继续查找。如果 你要用一个不同的位置覆盖内建模板时非常有用

class ChoiceLoader(loaders, cache_size=50, auto_reload=True)

 >>> loader = ChoiceLoader([

... FileSystemLoader('/path/to/user/templates'),

... PackageLoader('myapplication')

所有加载都继承自BaseLoader,如果你要实现一个自定义加载可以,可以写一个BaseLoader的子类,并覆盖get_source方 法。

 class BaseLoader(cache_size=50, auto_reload=True)

一个简单的例子

 from Jinja2 import BaseLoader, TemplateNotFound

from os.path import join, exists, getmtime

class MyLoader(BaseLoader):

def __init__(self, path, cache_size=50, auto_reload=True):

BaseLoader.__init__(self, cache_size, auto_reload)

self.path = path

def get_source(self, environment, template):

path = join(self.path, template)

if not exists(path):

raise TemplateNotFound(template)

mtime = getmtime(path)

with file(path) as f:

source = f.read().decode('utf-8')

return source, path, lambda: mtime != getmtime(path)

get_source(environment, template)

load(environment, name, globals=None)

加载一个模板。此方法会在缓存中查找模板,如果缓存中不存在则调用get_source得到模板的内容,缓存后返回结果。

注意,BaseLoader已经实现了load方法,它对模板的缓存进行了处理。如果你不需要自己维护缓存,则不必重写此方法。

Utilites

用来帮助你添加自定义过滤器或者函数到Jinja中

environmentfilter(f)

contextfilter(f)

environmentfunction(f)

contextfunction(f)

escape(s)

class Markup()

异常

类名 描述

class TemplateError() 所有模板异常的基类

class UndefinedError() 操作一个未定义对象时

class TemplateNotFound(name) 模板未找到

class TemplateSyntaxError(message, lineno, name) 模板语法错误

模板设计文档

概述

一个模板其实就是一个普通的文本文件。它可以被设计为任何文本格式(HTML,XML,CSV等等)。它也不需要确定的扩展名,不过一般我们都会 用'.html'或'.xml'

模板中包含变量,表达式,标签,变量和表达式会在模板渲染时被用值来替换,标签控制模板的逻辑。Jinja的语法主要参考自Django和 python。

下面是一个简单的模板,它包含的了几个模板中的基本元素,在之后的文档中会对这些元素做详细说明。

 

     

     

{{% for item in navigation %}}

         

  • {{ item.caption }}
  • {% endfor %}

         

    My Webpage

    {{ a_variable }}

    这个模板中包含了两种标记符"{% ... %}"与"{{ .. }}", 前者用来执行一个循环或者一个赋值语句,后者用来打印一个变量。

    变量

    你可以传递python的变量给模板,用来替换模板中的标记。这些变量可以是任何Python对象。在模板中可以直接操作传入的变量对象,也可以 访问这些变量的属性。

    访问变量属性有两种方式,一种是用"obj.attr"的方式,另一种是类似字典的方式:"obj['attr']".

     

    {{ foo.bar }}

    {{ foo['bar'] }}

    注意,上面的'{{ .. }}是Jinja的用来打印变量标记。如果要在其它标签中访问变量,则不能在变量名旁边加花括号。

    过滤器(filters)

    变量可以在模板中被过滤器修改. 使用过滤器的方式比较类似管道(pipe)操作。如:

      '{{ name|striptags|title }}'

    这个例子的意思是:将name变量用striptags消除变量值中的tag(用<>括起来的内容),再用title过滤器将首字符 大写。

    过滤器也可以接受参数,用起来比较像调用函数

     '{{ list|join(', ') }}'

    内建过滤器介绍参见内建过滤器一节。

    检查器(Tests)

    检查器用来在Jinja的if块里面检查一个变量是否符合某种条件。它的用法是 varname is atest, 例如检查一个变量是否存在

    {% if name is defined %}

    这里, defined就是一个检查器。

    检查器跟过滤器一样,也可以有参数,如果检查器只有一个参数,可以不写括号,直接用一个空格将检查器名和参数隔开,如下例中,两行代码的作用是一 样的:

    {% if loop.index is divisibleby 3 %}

    {% if loop.index is divisibleby(3) %}

    在后面的内建检查器列表一节中会介绍各个内建检查器

    注释

    Jinja中可以加入注释,如:

    {# note: disabled template because we no longer user this

    {% for user in users %}

    ...

    {% endfor %}

    #}

    这些注释内容不会出现在模板产生的文本中。

    模板继承

    模板继承是Jinja中一个非常有用的功能。这个功能允许你创建一个包含有所有公共元素的页面基本骨架,在子模板中可以重用这些公用的元素。

    使用模板继承其实很简单,下面我们开始用一个例子来介绍模板继承的用法。

    基础模板

    我们首先写一个名为"base.html"的模板,它包含下面的内容:

     

    {% block head %}

       

       

    {% endblock %}

       

    {% block content %}{% endblock %}

       

    {% block footer %}

    © Copyright 2008 by you.

    {% endblock %}

    在这个模板中有很多'block', 这些block中间的内容,我们将会在子模板中用其它内容替换。

    子模板

    我们再写一个名为"child.html"的模板,内容如下:

     

    {% extends "base.html" %}

    {% block title %}Index{% endblock %}

    {% block head %}

    {{ super() }}

       

    .important { color: #336699; }

    {% endblock %}

    {% block content %}

       

    Index

       

    Welcome on my awsome homepage.

       

    {% endblock %}

    :在这个模板的第一行,我们用{% extends "base.html" %}标明,这个模板将继承base.html.

    在随后的内容中包含了很多跟base.html中相同的block,如title,content,这些block中的内容将会替换 base.html的内容后输出.

    :extends后面的模板名称的写法依赖于此模板使用的模板加载器, 比如如果要使用FileSystemLoader,你可以在模板文件名中加入文件的文件夹名,如:

     

    {% extends "layout/default.html" %}

    在base.html中,我们定义了block “footer”,这个block在子模板中没有被重定义,那么Jinja会直接使用父模板中的内容输出。

    另外要注意,在同一个模板中不能定义名称相同的block。

    如果你要在模板中多次打印同一个block,可以用用self变量加上block的名字:

     

    {{ self.title() }}

    {% block body %}{% endblock %}

    和Python不同的地方是,Jinja不支持多继承。

    super block

    如果要在子模板中重写父模板的block中打印被重写的block的内容,可以调用super关键字。

     

    {% block sidebar %}

       

    Table Of Contents

    ...

    {{ super() }}

    {% endblock %}

     

    HTML转义

    :我们传递给模板的变量中可能会有一些html标记符,这些标记符也许会影响我们页面的正常显示,而且会给我们的站点带来跨站脚本攻击的隐患。

    Jinja提供了两种方式-自动或者手工来对变量值进行html转义,即把'<'转换为'<','>'转换为 '>','&'转换为'&'

    通过给Environment或Template的构建器传递autoescape参数,可以设置自动转义与否。

    手动转义

    这种方式需要我们使用过滤器转换我们需要转义的变量

    '{{ user.username|e }}'. 这里'e'就是转义过滤器

    自动转义

    这种方式会在打印变量时自动进行转义。除非使用'safe'过滤器标明不需要转义:

     

    '{{ user.username|safe }}'.

    结构控制标记

    Jinja中的控制标记包括:条件判断标记(if/elif/else),循环控制(for-loop),另外还有macro(宏)和上文中提到 的block。

    for

    循环打印一个序列,例如:

     

    Members

    {% for user in users %}

     

  • {{ user.username|e }}
  • {% endfor %}

    在循环内部,你可以访问一些特殊的变量

    Variable Description

    loop.index 当 前迭代的索引,从1开始算

    loop.index0 当前迭代的索引,从0开始算

    loop.revindex 相 对于序列末尾的索引,从1开始算

    loop.revindex0 相对于序列末尾的索引,从0开始算

    loop.first 相 当于 loop.index == 1.

    loop.last 相当于 loop.index == len(seq) - 1

    loop.length 序列的长度.

    loop.cycle 是 一个帮助性质的函数,可以接受两个字符串参数,如果当前循环索引是偶数,则显示第一个字符串,是奇数则显示第二个字符串。它常被在表格中用来用不同的背景 色区分相邻的行。

     

    {% for row in rows %}

       

  • {{ row }}
  • {% endfor %}

    需要注意的是,Jinja的循环不支持break和continue标记。你可以对需要迭代的sequence使用过滤器来达到与break和 continue相同的目的。

    下面的例子中,如果user.hidden属性为true的则continue

     

    {% for user in users if not user.hidden %}

       

  • {{ user.username|e }}
  • {% endfor %}

    Jinja的for语句有一个和python相同的用法,那就是“else':当无循环时显示else中的内容,如下例:

     

    {% for user in users %}

       

  • {{ user.username|e }}
  • {% else %}

       

  • no users found
  • {% endif %}

    if

    if语句用来在Jinja中做比较判断,比较常见的用法是判断一个变量是否已定义,是否非空,是否为true

     

    {% if users %}

    {% for user in users %}

       

  • {{ user.username|e }}
  • {% endfor %}

    {% 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语句也可以被用来做内联表达式或者for语句过滤器。

    宏(Macro)

    宏的作用和函数比较类似。用来把一部分常用的代码封装起来,避免重复性的工作。

    宏可以定义在一个帮助性质的模板中,用imported的方式被其它模板引用;也可以在模板中定义并直接使用。这两种方式有个显著的不同:在模板 中定义的宏可以访问传给模板的上下文变量;在其它模板中定义的宏则只能访问到传递给它的变量,或者全局变量。

    这里有个打印表单元素的简单的宏

     

    {% macro input(name, value='', type='text', size=20) -%}

    value|e }}" size="{{ size }}">

    {%- endmacro %}

    这个宏可以在命名空间中被直接调用

     

    {{ input('username') }}

    {{ input('password', type='password') }}

    如果这个宏在其它模板中,你必须先用import引入。

    在一个模板中你可以访问三种特殊变量:

    *'''varargs''' 等同于python语法中的"*args"

    *'''kwargs''' 等同于python语法中的"**kwargs"

    *'''caller''' 被call标签调用的宏,调用者会被存储在一个叫做caller的变量中。

    宏其实也是一个对象,它有一些属性可以在模板中使用:

    *'''name''' 宏的名称。{{ 'input.name':string }}

    *'''arguments''' 宏可以接受的参数,这个属性是一个元组

    *'''defaults''' 缺省值的元组

    *'''catch_kwargs''' 这个宏是否可以接受关键字参数

    *'''catch_varargs''' 这个宏是否可以接受索引位置参数

    *'''caller''' 是否有caller变量,可以被call标签调用

    Call

    在某些情况下,你可能需要将一个宏对象传递到另外一个宏中使用。为了实现此目的,你可以使用call block。

     

    {% macro render_dialog(title, class='dialog') -%}

       

           

    {{ title }}

           

    {{ caller() }}

    {%- endmacro %}

    {% call render_dialog('Hello World') %}

    This is a simple dialog rendered by using a macro and

    a call block.

    {% endcall %}

    在这里例子里,我们用"call render_dialog"调用了宏render_dialog,其中,'hello world作为render_dialog的title参数。在render_dialog中用{{ caller() }}将 call block中的内容显示出来。

    在使用 {{ caller() }} 时,也可以传入参数,如下例:

     

    {% macro dump_users(users) -%}

       

    {%- for user in users %}

           

  • {{ user.username|e }}

    {{ caller(user) }}
  • {%- endfor %}

    {%- endmacro %}

    {% call(user) dump_users(list_of_user) %}

       

           

    Realname

           

    {{ user.realname|e }}

           

    Description

           

    {{ user.description }}

    {% endcall %}

    赋值

    在一个代码块内部你可以为一个变量赋值。在块(block, macro, loop)外部赋值的变量可以被从模板中导出,提供给其它模板使用。

    一个赋值语句的用法如下例:

     

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

    include

    用include可以导入另外一个模板到当前模板中

     

    {% include 'header.html' %}

    Body

    {% include 'footer.html' %}

    import

    Jinja2支持将常用的代码放到宏中。这些宏可以放到不同的模板中,然后用import语句导入来使用,这有点类似python的import 功能。需要注意的是,import导入的模板会被缓存,而且导入到模板不能访问当前模板的本地变量,它只能访问全局变量。

    导入模板有两种方式,一是导入整个的模板作为一个变量,另一个方法是从一个模板中导入指定的宏或者可导出的变量

    下面我们写一个名为"form.html"的模板, 这个模板作为一个公共模板提供给其它模板使用

     

    {% macro input(name, value='', type='text') -%}

    {%- endmacro %}

    {%- macro textarea(name, value='', rows=10, cols=40) -%}

    }}">{{ value|e }}

    {%- endmacro %}

    最简单和灵活的方式是把form.html整个导入到一个模板中

     

    {% import 'forms.html' as forms %}

       

    Username

       

    {{ forms.input('username') }}

       

    Password

       

    {{ forms.input('password', type='password') }}

    {{ forms.textarea('comment') }}

    或者导入指定的内容(宏或者变量)到当前模板中

     

    {% from 'forms.html' import input as input_field, textarea %}

       

    Username

       

    {{ input_field('username') }}

       

    Password

       

    {{ input_field('password', type='password') }}

    {{ textarea('comment') }}

    表达式

    Jinja的表达式在模板中到处都是,它的语法很类似python,而且它很简单,即使不会python也可以很容易学会它。

    字面值

    字面值是最简单的表达式,它其实就是一个python的对象,在Jinja中有下面几种字面值:

    字符串,数字,序列,元组,字典,bool类型。

    它们的用法很python的很接近,如下面的例子:

     

    {% for href, caption in [('index.html', 'Index'), ('about.html', 'About'),

    ('downloads.html', 'Downloads')] %}

       

  • {{ caption }}
  • {% endfor %}

    数字计算

    Jinja支持一下几种操作符:

    +,-,/,//(整除),%求余,*乘,**次方

    逻辑操作

    Jinja支持一下几种逻辑操作符,它们可以放在if块中使用:

    and, or, not, ()

    其它操作符

    '''in '''

    判断一个对象是否存在于另一个序列或者元组中

     

    {{ 1 in [1, 2, 3] }}

    '''is'''

    执行一个检查器

    '''|'''

    执行一个过滤器

    '''~'''

    连接字符串 '{{ "Hello " ~ name ~ "!" }}',如果name的值是'world, 显示的内容将是 "Hello world"

    '''( )''' 调用函数

    '''. / []''' 访问一个对象的属性

    if表达式

    Jinja支持内联表达式,在某些情况下非常有用,例如:

     

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

    这个例子的意思是:如果变量layout_template已定义则导入,否则导入master.html

    通用的语法规则是''' if  else '''

    内建过滤器

    *'''abs(number)''' 返回数字的绝对值

    *'''batch(value, linecount, fill_with=None)'''

    :将一个序列以给定值分成若干片,如果给定了fill_with,则会将fill_with补充到未分配的部分。比如一个序列 ['a','b','c','d','e'], 用数值3分片将会得到[['a','b','c'], ['d','e']], 如果分片时指定fill_with=' ',结果将会是[['a','b','c'], ['d','e',' ']]

    :这个过滤器的用处在于,如果你要在表格中显示一个很长的序列,每行显示5个,则可以用下面的方式打印:

     

    {% for row in seq|batch(3, ' ') %}

    {% for item in row %}

    *'''capitalize(s)'''

    首字符大写

    *'''center(value, width=80)'''

    生成一个长度为width的空字符串,将value放在中间

    *'''default(value, default_value=u”, boolean=False)'''

    如果value未定义,则显示default_value,如果value是一个bool型,需要将boolean置为true,这样当value为 false是将会打印缺省值

    这个过滤器的别名是d

    *'''dictsort(value, case_sensitive=False, by='key')'''

    字典排序,case_sensitive决定是否大小写敏感,by决定是按照key排序还是按value排序

    *'''escape(s)'''

    html字符转义,别名是e

    *'''filesizeformat(value)'''

    将一个大数字转换成KMG形式,如:1.3k,34g,25.3m等等

    *'''first(seq)'''

    返回序列的第一个值

    *'''float(value, default=0.0)'''

    将一个值转换成浮点数,如果转换失败则返回default

    *'''forceescape(value)'''

    不管value是否被转义过,一律进行html转义。比如value="<", 如果用“value|e|e”则会得到“<",而不是"<",如果用forceescape则会得 到"<"

    *'''format(value, *args, **kwargs)'''

    等同于python的"%s,%s" % (str1, str2)

    *'''groupby(value, attribute)'''

    类似SQL的group by,可以将一个序列里的对象/字典,按照attribute分组。如下例:

     

    {% for group in persons|groupby('gender') %}

       

  • {{ group.grouper }}

  • {% for person in group.list %}

           

  • {{ person.first_name }} {{ person.last_name }}
  • {% endfor %}

    {% endfor %}

    也可以用下面的方式使用:

     

    {% for grouper, list in persons|groupby('gender') %}

    ...

    {% endfor %}

    "grouper"是分组的值,在上面的例子中分别是“male”和“female”

    *'''indent(s, width=4, indentfirst=False)'''

    将文本s中每行的首字符缩进width个字符。indentfirst表示是否缩进第一行。

    *'''int(value, default=0)'''

    将value转换成整数,如果转换失败则返回default

    *'''join(seq, d=u”)'''

    将序列seq中的各个值用d字符连接起来形成一个字符串。

    *'''last(seq)'''

    序列的最后一个值。

    *'''length(object)'''

    序列或者字典的长度

    别名:count

    *'''list(value)'''

    将value转换为序列,如果value是字符串,则将字符串转换为字符数组。

    *'''lower(s)'''

    将字符串转换为小写

    *'''pprint(value, verbose=False)'''

    debug时使用,可以打印变量的详细信息。

    *'''random(seq)'''

    随机从序列中取得一个值。

    *'''replace(s, old, new, count=None)'''

    将字符s中的old字符串替换为new字符串,如果给定了count,则最多替换count次。

    *'''reverse(value)'''

    将一个序列反转。

    *'''round(value, precision=0, method='common')'''

    浮点数求精。precision是小数点位数,method有common,ceil,floor三种。common是四舍五入,ceil和floor与 python的同名函数功能相同。

    *'''safe(value)'''

    如果当前模板设置了html自动转义,用此过滤器可以使value不转义

    *'''slice(value, slices, fill_with=None)'''

    将序列分片,用fill_with字符填充最后一组子序列长度不足的部分。

    *'''sort(value, reverse=False)'''

    将序列按从小到大排序,reverse为true则按从大到小排序

    *'''string(object)'''

    将一个对象转换为unicode字符串

    *'''striptags(value)'''

    去掉字符串value中的html,xml标签

    *'''sum(sequence, start=0)'''

    统计数值序列的和。start表示从第几项开始计算

    *'''title(s)'''

    将字符串s中每个单词首字符大写

    *'''trim(value)'''

    去掉字符串value中首尾的空格

    *'''truncate(s, length=255, killwords=False, end='...')'''

    截断一个字符串为length长度,末尾补end字符。killword为false则将最后一个单词完整保留,为True则将严格按照给定的长度截断。

    *'''upper(s)'''

    将字符串转换为大写

    *'''urlize(value, trim_url_limit=None, nofollow=False)'''

    *'''wordcount(s)'''

    统计字符串中单词的个数

    *'''wordwrap(s, pos=79, hard=False)'''

    将字符串s按照pos长度换行。如果hard为True,则强制截断单词。

    *'''xmlattr(d, autospace=True)'''

    创建一个sgml/xml的属性字符串,例如:

     

    ...

    结果会是这个样子:

     

    ...

    值会自动进行html转义,如果为未定义或者None则忽略。

    *'''autospace''': 自动在首部添加空格.

    内建检查器

    *'''callable(object)'''

    对象是否可调用

    *'''defined(value)'''

    对象是否已定义

    *'''divisibleby(value, num)'''

    value是否可以被num整除

    *'''escaped(value)'''

    是否已转义

    *'''even(value)'''

    是否为奇数

    *'''iterable(value)'''

    是否可以循环

    *'''lower(value)'''

    是否为小写

    *'''none(value)'''

    是否为None

    *'''number(value)'''

    是否为数字

    *'''odd(value)'''

    是否为偶数

    *'''sameas(value, other)'''

    value是否与other为同一个对象实例

    *'''sequence(value)'''

    是否为序列

    *'''string(value)'''

    是否是字符串

    *'''undefined(value)'''

    是否未定义

    *'''upper(value)'''

    是否为大写

    最后编辑于
    ©著作权归作者所有,转载或内容合作请联系作者
    • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
      沈念sama阅读 159,117评论 4 362
    • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
      沈念sama阅读 67,328评论 1 293
    • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
      开封第一讲书人阅读 108,839评论 0 243
    • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
      开封第一讲书人阅读 44,007评论 0 206
    • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
      茶点故事阅读 52,384评论 3 287
    • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
      开封第一讲书人阅读 40,629评论 1 219
    • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
      沈念sama阅读 31,880评论 2 313
    • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
      开封第一讲书人阅读 30,593评论 0 198
    • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
      沈念sama阅读 34,313评论 1 243
    • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
      茶点故事阅读 30,575评论 2 246
    • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
      茶点故事阅读 32,066评论 1 260
    • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
      沈念sama阅读 28,392评论 2 253
    • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
      茶点故事阅读 33,052评论 3 236
    • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
      开封第一讲书人阅读 26,082评论 0 8
    • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
      开封第一讲书人阅读 26,844评论 0 195
    • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
      沈念sama阅读 35,662评论 2 274
    • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
      茶点故事阅读 35,575评论 2 270

    推荐阅读更多精彩内容

    • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
      卡卡罗2017阅读 134,100评论 18 139
    • 项目配置 设置为DEBUG模式: 默认情况下flask不会开启DEBUG模式,开启DEBUG模式后,flask会在...
      编程小蝉阅读 3,482评论 0 9
    • Spring Boot 参考指南 介绍 转载自:https://www.gitbook.com/book/qbgb...
      毛宇鹏阅读 46,361评论 6 343
    • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
      子非鱼_t_阅读 31,295评论 18 399
    • 声明:转载请注明出处http://www.jianshu.com/p/1664dcfd840c 最近在折腾Djan...
      蛇发女妖阅读 6,206评论 1 10