内置全局函数

dict()函数,方便生成字典型变量

{% set user = dict(name='Mike',age=15) %}
<p>{{ user | tojson | safe }}</p> {# 显示 '{"age": 15, "name": "Mike"}' #}

joiner()函数,神奇的辅助函数。它可以初始化为一个分隔符,然后第一次调用时返回空字符串,以后再调用则返回分隔符。对分隔循环中的内容很有帮助

{% set sep = joiner("|") %}
{% for val in range(5) %}
{{ sep() }} <span>{{ val }}</span>
{% endfor %} {# 显示 "0 | 1 | 2 | 3 | 4" #}

cycler()函数,在给定的序列中轮循,列表项<li>的”class”在”odd”和”even”两个值间轮循

{% set cycle = cycler('odd', 'even') %}
<ul>
{% for num in range(10, 20, 2) %}
<li class="{{ cycle.next() }}">Number is "{{ num }}",
next line is "{{ cycle.current }}" line.</li>
{% endfor %}
</ul>

“cycler()”函数返回的对象可以做如下操作

    • next(),返回当前值,并往下一个值轮循
    • reset(),重置为第一个值
    • current,当前轮循到的值

自定义全局函数

将Flask应用代码中定义的函数,通过”add_template_global”将其传入模板即可

import re
def accept_pattern(pattern_str):
pattern = re.compile(pattern_str, re.S)
def search(content):
return pattern.findall(content) return dict(search=search, current_pattern=pattern_str) app.add_template_global(accept_pattern, 'accept_pattern')

上例中的accept_pattern函数会先预编译一个正则,然后返回的字典中包含一个查询函数”search”,之后调用”search”函数就可以用编译好的正则来搜索内容了。”app.add_template_global”方法的第一个参数是自定义的全局函数,第二个是全局函数名称。现在,让我们在模板中使用”accept_pattern”全局函数:

{% with pattern = accept_pattern("<li>(.*?)</li>") %}
{% set founds = pattern.search("<li>Tom</li><li>Bob</li>") %}
<ul>
{% for item in founds %}
<li>Found: {{ item }}</li>
{% endfor %}
</ul>
<p>Current Pattern: {{ pattern.current_pattern }}</p>
{% endwith %}

“Tom”和”Bob”被抽取出来了

Flask同样提供了添加全局函数的装饰器”template_global”,以方便全局函数的添加。我们来用它将取系统当前时间的函数”current_time”定义为全局函数。

import time
@app.template_global('end_with')
def current_time(timeFormat="%b %d, %Y - %H:%M:%S"):
return time.strftime(timeFormat)
<p>Current Time is: {{ current_time() }}</p>
<p>Current Day is: {{ current_time("%Y-%m-%d") }}</p>

Flask添加全局函数的方法是封装了对Jinja2环境变量的操作。上述添加”current_time”全局函数的方法,等同于下面的代码。

app.jinja_env.globals['current_time'] = current_time

宏 (Macro)

{% macro input(name, type='text', value='') -%}
<input type="{{ type }}" name="{{ name }}" value="{{ value|e }}">
{%- endmacro %}
<p>{{ input('username', value='user') }}</p>
<p>{{ input('password', 'password') }}</p>
<p>{{ input('submit', 'submit', 'Submit') }}</p>

访问调用者内容

先来创建个宏”list_users”:

{% macro list_users(users) -%}
<table>
<tr><th>Name</th><th>Action</th></tr>
{%- for user in users %}
<tr><td>{{ user.name |e }}</td>{{ caller() }}</tr>
{%- endfor %}
</table>
{%- endmacro %}

调用者的代码:

{% set users=[{'name':'Tom','gender':'M','age':20},
{'name':'John','gender':'M','age':18},
{'name':'Mary','gender':'F','age':24}]
%} {% call list_users(users) %}
<td><input name="delete" type="button" value="Delete"></td>
{% endcall %}

与上例不同,这里我们使用了”{% call %}”语句块来调用宏,语句块中包括了一段生成”Delete”按钮的代码。运行下试试,你会发现每个用户名后面都出现了”Delete”按钮,也就是”{{ caller( ) }}”部分被调用者”{% call %}”语句块内部的内容替代了,个人觉得,主要是有些时候HTML语句太复杂(如上例),不方便写在调用参数上,所以就写在”{% call %}”语句块里了。

Jinja2的宏不但能访问调用者语句块的内容,还能给调用者传递参数

首先,我们将表格增加一列性别,并在宏里调用”caller()”方法时,传入一个变量”user.gender”:

{% macro list_users(users) -%}
<table>
<tr><th>Name</th><th>Gender</th><th>Action</th></tr>
{%- for user in users %}
<tr><td>{{ user.name |e }}</td>{{ caller(user.gender) }}</tr>
{%- endfor %}
</table>
{%- endmacro %}

修改下调用者语句块:

{% call(gender) list_users(users) %}
<td>
{% if gender == 'M' %}
<img src="{{ url_for('static', filename='img/male.png') }}" width="20px">
{% else %}
<img src="{{ url_for('static', filename='img/female.png') }}" width="20px">
{% endif %}
</td>
<td><input name="delete" type="button" value="Delete"></td>
{% endcall %}

我们在使用”{% call %}”语句时,将其改为了”{% call(gender) … %}”,这个括号中的”gender”就是用来接受宏里传来的”user.gender”变量。因此我们就可以在”{% call %}”语句中使用这个”gender”变量来判断用户性别。这样宏就成功地向调用者传递了参数。

宏的内部变量

宏的内部可以使用”caller( )”方法获取调用者的内容。此外宏还提供了两个内部变量:

varargs

这是一个列表。如果调用宏时传入的参数多于宏声明时的参数,多出来的没指定参数名的参数就会保存在这个列表中。

kwargs

这是一个字典。如果调用宏时传入的参数多于宏声明时的参数,多出来的指定了参数名的参数就会保存在这个字典中。

{% macro input(name, type='text', value='') -%}
<input type="{{ type }}" name="{{ name }}" value="{{ value|e }}">
<br /> {{ varargs }}
<br /> {{ kwargs }}
{%- endmacro %}
<p>{{ input('submit', 'submit', 'Submit', 'more arg1', 'more arg2', ext='more arg3') }}</p>

可以看到,varargs变量存了参数列表”[‘more arg1’, ‘more arg2’]”,而kwargs字典存了参数”{‘ext’:’more arg3′}”。

当”include”的模板文件不存在时,程序会抛出异常。你可以加上”ignore missing”关键字,这样如果模板不存在,就会忽略这段”{% include %}”语句。

   {% include 'footer.html' ignore missing %}

   {% include ['footer.html','bottom.html','end.html'] ignore missing %}

上例中,程序会按顺序寻找模板文件,第一个被找到的模板即被加载,而其后的模板都会被忽略。如果都没找到,那整个语句都会被忽略。

Flask jinja2 全局函数,宏的更多相关文章

  1. MFC全局函数开局——AfxGetApp解剖

    MFC中有不少的全局函数,方便在不同对象中获取不同的内容或创建不同的对象.主要全局函数有: AfxWinInit() AfxBeginThread() AfxEndThread() AfxFormat ...

  2. Lua和C++交互 学习记录之六:全局函数交互

    主要内容转载自:子龙山人博客(强烈建议去子龙山人博客完全学习一遍) 部分内容查阅自:<Lua 5.3  参考手册>中文版 译者 云风 制作 Kavcc vs2013+lua-5.3.3 1 ...

  3. 初探 Python Flask+Jinja2 SSTI

    初探 Python Flask+Jinja2 SSTI 文章首发安全客:https://www.anquanke.com/post/id/226900 SSTI简介 SSTI主要是因为某些语言的框架中 ...

  4. CI框架源码阅读笔记3 全局函数Common.php

    从本篇开始,将深入CI框架的内部,一步步去探索这个框架的实现.结构和设计. Common.php文件定义了一系列的全局函数(一般来说,全局函数具有最高的加载优先权,因此大多数的框架中BootStrap ...

  5. jQuery全局函数

    全局函数是对jQuery对象的扩展,其中扩展方法包括: 一,extend扩展: //调用全局函数$(document).ready(function () { $.myFunction(); $.my ...

  6. 部分具有统计功能的TSQL语句(例如DBCC语句,全局函数,系统存储过程)

    部分具有统计功能的TSQL语句(例如DBCC语句,全局函数,系统存储过程) 这些功能也能帮助用户了解和监控SQLSERVER的运行情况 DBCC语句,DBCC语句是SQL2005的数据库控制台命令 D ...

  7. JavaScript基础11——js的全局函数

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  8. 在C++工程中设置全局函数

    在头文件中对该函数进行全局函数的声明: extern void Test(); 在cpp文件中进行函数的定义: void Test() { MessageBox(NULL,L"调用了C++的 ...

  9. C++学习27 用全局函数重载运算符

    运算符重载函数既可以声明为类的成员函数,也可以声明为所有类之外的全局函数. 运算符重载函数作为类的成员函数 将运算符重载函数声明为类的成员函数时,二元运算符的参数只有一个,一元运算符不需要参数.之所以 ...

随机推荐

  1. 【POJ2387】Til the Cows Come Home (最短路)

    题面 Bessie is out in the field and wants to get back to the barn to get as much sleep as possible bef ...

  2. [BZOJ1507] [NOI2003] Editor (splay)

    Description Input 输入文件editor.in的第一行是指令条数t,以下是需要执行的t个操作.其中: 为了使输入文件便于阅读,Insert操作的字符串中可能会插入一些回车符,请忽略掉它 ...

  3. 图文详解AO打印(标准模式)

    一.概述   AO打印是英文Active-Online Print的简称,也称主动在线打印.打印前支持AO通讯协议的AO打印机(购买地址>>)首先通过普通网络与C-Lodop服务保持在线链 ...

  4. 什么是Docker??

    ​​Docker是一个轻量级虚拟机,也是一种Linux容器,它突破了以往的沙盒技术,解放了应用部署,让PaaS的应用场景更为广泛. ​ docker是通过内核虚拟化技术((namespaces及cgr ...

  5. 软件测试必备-前端知识点之css基础及ps的用法

    CSS 一. css定义 css样式表.层叠样式表,级联样式表 二. css基础语法 1. 写style标签,放在head标签里面的最后位置 2. 自己写的css代码,放在style标签里面 三. c ...

  6. border-image的拉伸和平铺

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  7. java ssm框架实现分页功能 (oracle)

    java web 实现分页功能 使用框架:ssm 数据库:oracle 话说 oracle 的分页查询比 mysql 复杂多了,在这里简单谈一下: 查询 前十条数据: SELECT * FROM( S ...

  8. Redis分布式锁的正确实现方式

    前言 分布式锁一般有三种实现方式:1. 数据库乐观锁:2. 基于Redis的分布式锁:3. 基于ZooKeeper的分布式锁.本篇博客将介绍第二种方式,基于Redis实现分布式锁.虽然网上已经有各种介 ...

  9. [Usaco 5.4] Telecowmunication

    Description 农夫约翰的奶牛们喜欢通过电邮保持联系,于是她们建立了一个奶牛电脑网络,以便互相交流.这些机器用如下的方式发送电邮:如果存在一个由c台电脑组成的序列a1,a2,...,a(c), ...

  10. 笔记:Maven 依赖及配置详解

    dependencies 配置节,主要用于配置项目依赖的其他包,其子节点 dependency 用来配置具体依赖包,有groupId.artifactId.version.scope等子节点来说明,配 ...