当前位置: 首页 > news >正文

Flask的Jinja2模板引擎 - 全局函数

为什么80%的码农都做不了架构师?>>>   hot3.png

Jinja2模板引擎的另一个辅助函数功能,即全局函数Global Functions。如果说过滤器是一个变量转换函数,测试器是一个返回布尔值的函数,那全局函数就可以是任意函数。可以在任一场景使用,没有输入和输出值的限制。本篇我们就来阐述下这个全局函数。

全局函数使用

还是取出第一篇开篇的代码,我们在模板中加入下面的代码:

<ul>
{% for num in range(10, 20, 2) %}
    <li>Number is "{{ num }}"</li>
{% endfor %}
</ul>

页面上会显示”10,12,14,16,18″5个列表项。全局函数”range()”的作用同Python里的一样,返回指定范围内的数值序列。三个参数分别是开始值,结束值(不包含),间隔。如果只传两个参数,那间隔默认为1;如果只传1个参数,那开始值默认为0。
由此可见,全局函数如同其名字一样,就是全局范围内可以被使用的函数。其同第二篇介绍的上下文环境中定义的函数不同,没有请求生命周期的限制。

内置全局函数

演示几个常用的内置全局函数。
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()函数,作用同第一篇介绍的循环内置变量”loop.cycle”类似,在给定的序列中轮循

{% 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()”函数的使用,你会发现列表项<li>的”class”在”odd”和”even”两个值间轮循。加入第一篇中的CSS style,就可以看到斑马线了。
“cycler()”函数返回的对象可以做如下操作
next(),返回当前值,并往下一个值轮循
reset(),重置为第一个值
current,当前轮循到的值
更全的内置全局函数介绍可以从Jinja2的官方文档中找到。

自定义全局函数

我们当然也可以写自己的全局函数,方法同之前介绍的过滤器啦,测试器啦都很类似。就是将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”被抽取出来了,很牛掰的样子。你还可以根据需要在”accept_pattern”的返回字典里定义更多的方法。
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

我们在Flask应用中,不建议直接访问Jinja2的环境变量。如果离开Flask环境直接使用Jinja2的话,就可以通过”jinja2.Environment”来获取环境变量,并添加全局函数。
完整代码:

from flask import Flask,render_template

app = Flask(__name__)

@app.route('/hello')
@app.route('/hello/<name>')
def hello(name=None):
    return render_template('hello-5.html', name=name)

########## Add Global Functions ##########
import time
@app.template_global('current_time')
def current_time(timeFormat="%b %d, %Y - %H:%M:%S"):
    return time.strftime(timeFormat)

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')

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

if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

模板

<!doctype html>
<title>Hello Sample</title>
<style type="text/css">
    .odd {
        background-color: #BDF;
    }
</style>

{% if name %}
  <h1>Hello {{ name }}!</h1>
{% else %}
  <h1>Hello World!</h1>
{% endif %}

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

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

{# 显示 '{"age": 15, "name": "Mike"}' #}


{% set sep = joiner("|") %}
{% for val in range(5) %}
    {{ sep() }} <span>{{ val }}</span>
{% endfor %}

{# 显示 "0 | 1 | 2 | 3 | 4" #}


<p>Current Time is: {{ current_time() }}</p>
<p>Current Day is: {{ current_time("%Y-%m-%d") }}</p>

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

 

转载于:https://my.oschina.net/yehun/blog/870929

相关文章:

  • 二叉树性质
  • Win10系列:C#应用控件基础2
  • Ubuntu下搭建tftp服务器最简单方法
  • PHP基础笔记【2】字符串操作
  • 深入分析Java单例模式的各种方案
  • 左手书法二十七篇
  • Flink - NetworkEnvironment
  • 修改Jmeter配置使能支持更大并发
  • 关于grep正则表达式-1
  • web前端性能优化总结
  • Cloudera Manager是啥?主要是干啥的?
  • Android中的动画,选择器,样式和主题的使用
  • 基于zedboard的DMA设计笔记
  • WePY 在小程序性能调优上做出的探究
  • EL表达式学习笔记
  • [NodeJS] 关于Buffer
  • 【399天】跃迁之路——程序员高效学习方法论探索系列(实验阶段156-2018.03.11)...
  • 【mysql】环境安装、服务启动、密码设置
  • conda常用的命令
  • CSS3 变换
  • Python_网络编程
  • Spring声明式事务管理之一:五大属性分析
  • uni-app项目数字滚动
  • vue 个人积累(使用工具,组件)
  • Vultr 教程目录
  • 阿里云Kubernetes容器服务上体验Knative
  • 函数式编程与面向对象编程[4]:Scala的类型关联Type Alias
  • 检测对象或数组
  • 收藏好这篇,别再只说“数据劫持”了
  • 双管齐下,VMware的容器新战略
  • 小程序 setData 学问多
  • 一个SAP顾问在美国的这些年
  • ​Linux·i2c驱动架构​
  • # include “ “ 和 # include < >两者的区别
  • ()、[]、{}、(())、[[]]命令替换
  • (4)logging(日志模块)
  • (ibm)Java 语言的 XPath API
  • (JS基础)String 类型
  • (python)数据结构---字典
  • (SpringBoot)第七章:SpringBoot日志文件
  • (ZT)北大教授朱青生给学生的一封信:大学,更是一个科学的保证
  • (二)七种元启发算法(DBO、LO、SWO、COA、LSO、KOA、GRO)求解无人机路径规划MATLAB
  • (二十一)devops持续集成开发——使用jenkins的Docker Pipeline插件完成docker项目的pipeline流水线发布
  • (附源码)spring boot基于小程序酒店疫情系统 毕业设计 091931
  • (附源码)springboot 基于HTML5的个人网页的网站设计与实现 毕业设计 031623
  • (附源码)springboot猪场管理系统 毕业设计 160901
  • (附源码)计算机毕业设计SSM疫情居家隔离服务系统
  • (三)Hyperledger Fabric 1.1安装部署-chaincode测试
  • (三)mysql_MYSQL(三)
  • (转)MVC3 类型“System.Web.Mvc.ModelClientValidationRule”同时存在
  • *2 echo、printf、mkdir命令的应用
  • .htaccess 强制https 单独排除某个目录
  • .NET Core中的去虚
  • .php结尾的域名,【php】php正则截取url中域名后的内容
  • :not(:first-child)和:not(:last-child)的用法