jinja2

最後更新: 2015-09-09

介紹

Jinja is a fast, expressive, extensible templating engine.

  • sandboxed execution
  • powerful automatic HTML escaping system
  • template inheritance

目錄

  • Install jinja2
  • Test it
  • Jinja2 with webpy
  • "with" Statement
  • Escaping
  • Filters
  • Control Structures
  • Whitespace Control
  • Include
  • Macros
  • Template Inheritance
  • i18n
  • Doc

Syntas:

{% set var=3 %}     # for Statements

{{ var }}                 # call variable

{# Comment #}       # for Comments not included in the template output

Math

+, -, /, // (20//7=2), %, *, **

i.e.

{{ 1 / 2 }}

Comparisons

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

Logic

and, or, not, (group)

Operators

in, is, | (filter)

 


Install jinja2

 

yum

yum install python-jinja2           # Centos 7

pip

pip install jinja2

pip install jinja2==2.11

 * jinja2 depends on the MarkupSafe module

    MarkupSafe 比 jinja 自帶的 Markup 行得怏, 建議使用它

 


Test it

 

test.py

from jinja2 import Template

template = Template('Hello {{name}}!')   # template 格式
msg = template.render(name='datahunter') # dict or keywords arguments
print msg                                # Hello datahunter!

python test.py

 


Variable in template

 

{{ a_variable }}

"." , [''] to access attributes of a variable

  • {{ foo.bar }}                    # 較短
  • {{ foo['bar'] }}

* If a variable or attribute does not exist you will get back an undefined value.

提取 data 時會有兩個情況

  • Value
  • Null        #  access variable undefined value
  • Error       # access object undefined attribute

data.title   # 拎 attr 時

<class 'jinja2.exceptions.UndefinedError'> at /

 


Jinja2 with webpy

 

hello.py

import web
from web.contrib.template import render_jinja

urls = (
    "/", "hello",
)

render = render_jinja(
    'templates',              # Set template directory.
    encoding = 'utf-8',       # Set html 檔的 Encoding(utf-8 ...)
)

app = web.application(urls, globals(), autoreload=True)

class hello:
    def GET(self):
        return render.hello(title='test msg')

if (__name__ == "__main__"):
    app.run()
else:
    application = app.wsgifunc()

templates/hello.html

<html>
    <head><title>{{name}}</title></head>
    <body>My title is {{name}}</body>
</html>

 


"with" Statement

 

with: create a new inner scop

{% with %}
    {% set foo = 42 %}
    {{ foo }}           foo is 42 here
{% endwith %}

# foo is not visible here any longer
{{ foo }}

 


Function

 

seq

{% set seq = [1,2,3] %}

 


Escaping

 

<1>

{{ '{{' }}

<2>

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

 


Filters

 

Variables can be modified by filters

{{ variable|filter }}
{{ variable|filter1|filter2 }}
{{ list|join(', ') }}

builtin-filters:

  • lower
  • center
  • forceescape
  • trim
  • truncate(length=255)
  • urlencode
  • wordwrap(width=79)
  • striptags                    # Strip SGML/XML tags and replace adjacent whitespace by one space.
  • join(', ')

 


Control Structures

 

for

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

支援 continue, break

{% continue %}, {% break %}

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

special variables:

  • loop.index
  • loop.first
  • loop.last
  • loop.length

 

if

<1>

{% if pageinfo.saveLogin == "on" %}
    .........
{% endif %}

<2>

i.e. 1

{% if variable is defined %}
    value of variable: {{ variable }}
{% else %}
    variable is not defined
{% endif %}

i.e. 2

{% if loop.index is divisibleby 3 %}

Builtin Tests

  • divisibleby N
  • callable
  • defined, undefined
  • equalto
  • none
  • string, number
  • iterable
  • odd, even
  • upper, lower
  • mapping (dict)

i.e. 3

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

 


Whitespace Control

 

* Jinja2 by default 係會 keep whitespace (spaces, tabs) 及 頭一行 newline

Example:

* 它們是有不同的

<!-- 1 -->
<div>
    {% if True %}
        yay
    {% endif %}
</div>

<!-- 2 -->
<div>
    {% if True %} 1 {% endif %}
    {% if True %} 2 {% endif %}
</div>

的 result 是

<!-- 1 -->
<div>
                 # 多了頭這一空行
        yay      # yay 前面有空格
                 # 多了尾這一空行
</div>

<!-- 2 -->
<div>
     1           # 一句 statment 係會佔用一行的
     2
</div>

(-) 移除了尾的 newline. "-" 在不同的角會有不同的意思)

ie.1

{% set seq = [1,2,3] %}
<div>
<!-- 不要頭空行 -->
{%- for item in seq %}         
    {{ item }}
{% endfor -%}
<!-- 不要尾空行 -->
</div>

result:

<div>
    1
    2
    3
</div>

ie.2 不要頭空行空格

{% set seq = [1,2,3] %}
<div>
{% for item in seq -%}         
    {{ item }}
{% endfor %}
</div>

result:

<div>
1
2
3

</div>

ie.3 一行過

{% set seq = [1,2,3] %}
<div>
{% for item in seq -%}         
    {{ item }}
{%- endfor %}
</div>

 


Include

 

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

 


Macros

 

macro code(file: forms.html)

{% macro input(name, value='', type='text', size=20) -%}
    <input type="{{ type }}" name="{{ name }}" value="{{
        value|e }}" size="{{ size }}">
{%- endmacro %}

use it(same file)

<p>{{ input('username') }}</p>
<p>{{ input('password', type='password') }}</p>

Import

 * forms.html 裝了 macro 的 code

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

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

 


Template Inheritance

 

Base Template - base.tmpl

用 "{% block NAME %}...{% endblock %}" 定義了 4 個 block

<html lang="en">
<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>

Child Template - child.tmpl

{% extends "base.tmpl" %}

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

 

同名的 macro

layout.tmpl:

{% macro foo() %}LAYOUT{% endmacro %}
{% block body %}{% endblock %}

child.tmpl:

{% extends 'layout.tmpl' %}
{% macro foo() %}CHILD{% endmacro %}
{% block body %}{{ foo() }}{% endblock %}

Result: LAYOUT !!

 


i18n

 

* wrapped string as translatable and calls gettext

template:

{{ _('Hello World!') }}

i18n\zh_TW\LC_MESSAGES

  • mo
  • po

 


Doc

 

https://jinja.palletsprojects.com/en/2.11.x/

 

 

 

Creative Commons license icon Creative Commons license icon