最後更新: 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 %} © 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/