jinja2 基本语法
如果你只是配合 flask 使用 jinja2,那么 Template Designer Documentation 的这部分文档基本就够了,另一部分的 API
文档是面向那些比如说使用 jinja2 作为一个模板程序什么的。好了,正文开始。
The default Jinja delimiters:
{% ... %}for Statements{{ ... }}for Expressions to print to the template output{# ... #}for Comments not included in the template output# ... ##for Line Statements
variable
{{ variable }}; 获得 attribute 可以使用 {{ variable.attr }} 或者 {{ variable['attr'] }}, 两者等同;
设置 variable: {% set name='lord63' %}
Block Assignments:
{% set navigation %} <li><a href="/">Index</a> <li><a href="/downloads">Downloads</a> {% endset %}
if
{% if age < 18 %} <p>You're not allowed to come in.</p> {% endif %} {% if kenny.sick %} Kenny is sick. {% elif kenny.dead %} You killed Kenny! You bastard!!! {% else %} Kenny looks okay --- so far {% endif %}
for
{% for user in users %} <li>{{ user.username|e }}</li> {% endfor %}
comment
{# a block or a line #} or ## one line
filters
Do something on the variable, seperated by |, can be chained. e.g. {{ items|join(', ') }}.
List of Builtin Filters
tests
Test a variable against a common expression. e.g. {% if loop.index is divisibleby(3) %}.
List of Builtin Tests
reuse your code
在我看来呢,inheritence 就像类,子模板集成父模板的,比如你定义一个基本的 layout.html,所有的页面都是继承扩展这个模板的,
是一个通用基础; macro 就像函数,你把重复要用的放到一个 macro 中,重复利用。它是可拔插的,有的页面要用,就 import 进来,
因为如果每个页面都是要用的,就应该放到 layout.html 的基本模板中了。那么 include 的呢,我个人感觉就是为了更好的组织模板。
就像你会把一个 1000 行的文件分开来放在不同的文件中,虽然效果都是一样,但是每个文件目的性更加明确了,层次更加清楚了。
macros
Macros are comparable with functions in regular programming languages.
my_macro.html
{% macro input(name, value='', type='text', size=20) -%} <input type="{{ type }}" name="{{ name }}" value="{{ value|e }}" size="{{ size }}"> {%- endmacro %}
index.html
{% from 'my_macro.html' import input %} ... <p>{{ input('username') }}</p> ...
inheritence
base.html
{% block style } <link rel="stylesheet" href="http://blabla.css"> {% endblock %} ... {% block content }{% endblock %} ...
index.hytml(render the contents of the parent block by calling super)
{% extends 'base.html' %} {% block style %} {{ super() }} <link rel="stylesheet" href="http://foobar.css"> {% endblock %} {% block content %} <p> Hello, world.</p> {% endblock %}
include
index.html
... <p>This is the index page.</p> {% include 'footer.html' %}
footer.html
<p>Powered by Flask.</p>
jinja2 in flask
最基本的就是 render_template('name.html', **kargs). 在 flask 中 jinja2 的使用更应该重视的是对模板文件的组织和分割,
具体的用法比如说 filters,tests 的细节直接翻文档就可以了。
default context
- config
- g
- request
- session
- url_for
- get_flashed_messages
Documentation - Standard Context
template filter, template test, template global
- register custom template filter: template_filter(name=None) or add_template_filter(f, name=None)
- register custom template test: template_test(name=None) or add_template_test(f, name=None)
- register a custom template global function: template_global(name=None) or
add_template_global(f, name=None)
三者分别对应 jinja2 中的 filter,test,global functions。前者是 decorator 用法,后者是实际底层调用的。
这个就像是平时我们一般用的 route 的 decorator 来定义路由,你也可以使用 add_url_rule 来实现,因为 route
这个 decorator 实际上就是 add_url_rule 的 wrapper。还有一点要提一下,有时候你可能会在使用 decorator 用法时忘记了 (),
这时候你想一想,这三个都是有一个 name 参数来使用你自定义的名字,所以是应该有 (), 因为我们平时都是没有定义而默认使用函数的名字,
所以记得加上 ().
Blueprint 也有对应的方法,只不过名字前多了一个 app,比如说 template_filter(name=None) -> app_template_filter(name=None).
故不再说明,用法是一样的。
flask template context processor
首先稍微定义一下 template context,jinja2 的文档中稍微提到了一下:
The dict or keywords arguments passed to the template are the so-called “context” of the template.
关于 template context processor 的用法,举个例子来说:
@app.context_processor def inject_user(): return dict(user='lord63')
这样的话,在模板文件中就直接可以使用 {{ name }} 了,不用再手动传进去了。当然,你也完全可以传个函数,
效果有点像 template_global()。
@app.context_processor def inject_user(): def say_hi(name): return "hello, {0}".format(name) return dict(say_hi=say_hi) {# in your template #} <p>say_hi('lord63')</p>