jinja

Jinja2的一些使用摘要

Jinja2作为flask的默认页面模板,感觉蛮强大的,可适用于各种模板类相关的项目

特别是模板继承,写页面很舒服


资源

文档 http://jinja.pocoo.org/docs/

安装

sudo easy_install jinja2
sudo pip install jinja2

终端版helloworld

>>> from jinja2 import Template
>>> template = Template('Hello {{ name }}!')
>>> template.render(name='World')
u'Hello World!'

{%和{{

<body>
    <ul id="navigation">
    {% for item in navigation %}
        <li><a href="{{ item.href }}">{{ item.caption }}</a></li>
    {% endfor %}
    </ul>

    <h1>My Webpage</h1>
    {{ a_variable }}
</body>

{% 用于执行语句

{{ 输出语句结果到模板

{{}}中的运算

{{ 1 + 1 }}
{{ 3 - 2 }}
{{ 1 / 2 }} is {{ 0.5 }}.
{{ 20 // 7 }} is 2
{{ 11 % 7 }} is 4
{{ 2 * 2 }} would return 4
{{ '=' * 80 }}
{{ 2**3 }}

变量

变量输出 - 获取属性的方法,都可以
{{ foo.bar }}
# 查属性 - 查子元素 - 没有报错

{{ foo['bar'] }}
# 查子元素 - 查属性 - 没有报错

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


# set and use it later
{% set mybool = [False] %}
{% set _ = mybool.append(not mybool.pop()) %}

注释

{# note: disabled template because we no longer use this
    {% for user in users %}
        ...
    {% endfor %}
#}

空格控制

<div>
    {% if True %}
        yay
    {% endif %}
</div>

默认,会执行 trim_blocks and lstrip_blocks

移除空格

{% for item in seq -%}
    {{ item }}
{%- endfor %}

seq = 1 to 9
得到 123456789

Escaping

简单的

{{ '{{' }}

{% raw %}
    <ul>
    {% for item in seq %}
        <li>{{ item }}</li>
    {% endfor %}
    </ul>
{% endraw %}

if分支判断

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


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

可用的条件操作符

==  Compares two objects for equality.
!=  Compares two objects for inequality.
>   true if the left hand side is greater than the right hand side.
>=  true if the left hand side is greater or equal to the right hand side.
<   true if the left hand side is lower than the right hand side.
<=  true if the left hand side is lower or equal to the right hand side.

逻辑连接符

and     Return true if the left and the right operand is true.
or      Return true if the left or the right operand is true.
not     negate a statement (see below).
(expr)  group an expression.

内置测试列表 http://jinja.pocoo.org/docs/templates/#builtin-tests

callable(object)
defined(value)
        {% if variable is defined %}
            value of variable: {{ variable }}
        {% else %}
            variable is not defined
        {% endif %}
divisibleby(value, num)
escaped(value)
even(value)
iterable(value)
lower(value)
mapping(value)
none(value)
number(value)
odd(value)
sameas(value, other)
    {% if foo.attribute is sameas false %}
        the foo attribute really is the `False` singleton
    {% endif %}
sequence(value)
string(value)
undefined(value)
upper(value)

for循环

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

<ul>
{% for user in users %}
    <li>{{ user.username|e }}</li>
{% else %}
    <li><em>no users found</em></li>
{% endfor %}
</ul>

循环体中可用变量

Variable        Description
loop.index      The current iteration of the loop. (1 indexed)
loop.index0     The current iteration of the loop. (0 indexed)
loop.revindex   The number of iterations from the end of the loop (1 indexed)
loop.revindex0  The number of iterations from the end of the loop (0 indexed)
loop.first      True if first iteration.
loop.last       True if last iteration.
loop.length     The number of items in the sequence.
loop.cycle      A helper function to cycle between a list of sequences. See the explanation below.
loop.depth      Indicates how deep in deep in a recursive loop the rendering currently is. Starts at level 1
loop.depth0     Indicates how deep in deep in a recursive loop the rendering currently is. Starts at level 0

filters

{{ name|striptags|title }}

一系列方法 内置filter列表 http://jinja.pocoo.org/docs/templates/#builtin-filters

abs(number)
attr(obj, name)   foo|attr("bar") works like foo["bar"]
                  just that always an attribute is returned and items are not looked up
batch(value, linecount, fill_with=None)
capitalize(s)
center(value, width=80)
default(value, default_value=u'', boolean=False)
                {{ my_variable|default('my_variable is not defined') }}
                {{ ''|default('the string was empty', true) }} 当变量false是,用default替换
dictsort(value, case_sensitive=False, by='key')
escape(s)
filesizeformat(value, binary=False)
first(seq)  Return the first item
float(value, default=0.0)
forceescape(value) Enforce HTML escaping
format(value, *args, **kwargs)
                {{ "%s - %s"|format("Hello?", "Foo!") }}
groupby(value, attribute)
indent(s, width=4, indentfirst=False)
                {{ mytext|indent(2, true) }}
int(value, default=0)
join(value, d=u'', attribute=None)
                {{ [1, 2, 3]|join('|') }}
last(seq)
length(object)
list(value)
lower(s)
map()
        {{ users|map(attribute='username')|join(', ') }}
pprint(value, verbose=False)
random(seq)
reject() Filters a sequence of objects by appying a test
        {{ numbers|reject("odd") }}
rejectattr()
        {{ users|rejectattr("is_active") }}
        {{ users|rejectattr("email", "none") }}
replace(s, old, new, count=None)
        {{ "aaaaargh"|replace("a", "d'oh, ", 2) }}
reverse(value)
round(value, precision=0, method='common')
        {{ 42.55|round }} 43
        {{ 42.55|round(1, 'floor') }} 42.5
safe(value)
        automatic escaping enabled this variable will not be escaped
select()
        {{ numbers|select("odd") }}
selectattr()
        {{ users|selectattr("is_active") }}
        {{ users|selectattr("email", "none") }}
slice(value, slices, fill_with=None)
sort(value, reverse=False, case_sensitive=False, attribute=None)
        {% for item in iterable|sort %}
        {% for item in iterable|sort(attribute='date') %}

string(object)
        x|string()
striptags(value)
sum(iterable, attribute=None, start=0)
        Total: {{ items|sum(attribute='price') }}
title(s)
trim(value)
truncate(s, length=255, killwords=False, end='...')
        {{ "foo bar"|truncate(5) }}   "foo ..."
        {{ "foo bar"|truncate(5, True) }}   "foo b..."
upper(s)
urlencode(value)
urlize(value, trim_url_limit=None, nofollow=False)
wordcount(s)
wordwrap(s, width=79, break_long_words=True, wrapstring=None)
xmlattr(d, autospace=True)

Macros宏

创建

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

定义

{% 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 %}

宏与宏之间的交互

{% 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 %}

模板继承

父模板

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

子模板

{% 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 %}

注意,可以有更好的可读性

{% block sidebar %}
    {% block inner_sidebar %}
        ...
    {% endblock inner_sidebar %}
{% endblock sidebar %}

模板包含include

{% include 'header.html' %}
    Body
{% include 'footer.html' %}

#jinja2.2
{% include "sidebar.html" ignore missing %}
{% include "sidebar.html" ignore missing with context %}
{% include "sidebar.html" ignore missing without context %}

其他

1.一些列表方法

http://jinja.pocoo.org/docs/templates/#list-of-global-functions

2.其他操作符

in      Perform sequence / mapping containment test. Returns true if the left operand is contained in the right. {{ 1 in [1, 2, 3] }} would for example return true.
is      Performs a test.
|       Applies a filter.
~       Converts all operands into strings and concatenates them. {{ "Hello " ~ name ~ "!" }} would return (assuming name is 'John') Hello John!.
()      Call a callable: {{ post.render() }}. Inside of the parentheses you can use positional arguments and keyword arguments like in python: {{ post.render(user, full=true) }}.
. / []  Get an attribute of an object. (See Variables)

3.range, 可以正常使用range

{% for n in range(n) %}
    {{n}}
{% endfor %}

The end. 未完待续

wklken

http://www.wklken.me

2013-12-21