Flask模板渲染

Jinja2模板引擎简介

模板

视图函数的主要作用是生成请求的响应,这是最简单请求.实际上,视图函数有两个作用:

  • 处理业务逻辑
  • 返回响应内容

在大型应用中,把业务逻辑和表现内容放在一起,会增加代码的复杂度和维护成本.

  • 模板其实是一个包含响应文本的文件,其中用占位符(变量)表示动态部分,告诉模板引擎其具体的值需要从使用的数据中获取
  • 使用真实值替换变量,再返回最终得到的字符串,这个过程称为'渲染'
  • Flask是使用Jinja2这个模板引擎来渲染模板

使用模板的好处

  • 视图函数只负责业务逻辑和数据处理(业务逻辑方面)
  • 而模板则取到视图函数的数据结果进行展示(试图展示方面)
  • 代码结构清晰,耦合度低

Jinja2

两个概念

  • Jinja2:是Python下一个被广泛应用的模板引擎,是由Python实现的模板语言,他的设计思想来源于Django的模板引擎,并扩展了其语法和一系列强大的功能,其是Flask内置的模板语言
  • 模板语言:是一种被设计来自动生成文档的简单文本格式,在模板语言中,一般都会把一些变量传给模板,替换模板的特定位置上预先定义好的占位变量名

渲染模板函数

  • Flask提供的render_template函数封装了该模板引擎
  • render_template函数的第一个参数是模板的文件名,后面的参数都是键值对,表示模板中变量对应的真实值

模板变量

变量

  • 代码中传入字符串,列表,字典到模板中

    @app.route('/')
    def index():
    # 往模板中传入的数据
    my_str = 'Hello Word' # 字符串
    my_int = 10 # 数字
    my_array = [3, 4, 2, 1, 7, 9] # 列表
    my_dict = { # 字典
    'name': 'xiaoming',
    'age': 18,
    'weight': 125,
    }
    return render_template('temp_demo1.html',
    my_str=my_str,
    my_int=my_int,
    my_array=my_array,
    my_dict=my_dict
    )
  • 模板中代码

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    </head>
    <body>
    我的模板html内容
    <br/>{{ my_str }}
    <br/>{{ my_int }}
    <br/>{{ my_array }}
    <br/>{{ my_dict }} </body>
    </html> <!--
    运行结果:
    我的模板html内容
    Hello Word
    10
    [3, 4, 2, 1, 7, 9]
    {'name': 'xiaoming','age': 18,'weight': 125}
    -->
  • 列表、字典的取值运算

    <!--算数运算-->
    <br/> my_int + 10 的和为:{{ my_int + 10 }} <!--列表取值
    1. list[index]
    2. list.index
    -->
    <br/> my_int + my_array第0个值的和为:{{ my_int + my_array[0] }}
    <br/> my_array 第0个值为:{{ my_array[0] }}
    <br/> my_array 第1个值为:{{ my_array.1 }} <!--字典取值
    1. dict.key
    2. dice[key]
    3. dict.get(key)
    -->
    <br/> my_dict 中 name 的值为:{{ my_dict['name'] }}
    <br/> my_dict 中 age 的值为:{{ my_dict.age }}
    <br/> my_dict 中 weight 的值为:{{ my_dict.get('weight') }} <!--
    运行结果:
    my_int + 10 的和为:20
    my_int + my_array第0个值的和为:13
    my_array 第0个值为:3
    my_array 第1个值为:4
    my_dict 中 name 的值为:xiaoming
    my_dict 中 age 的值为:18
    my_dict 中 weight 的值为:125 -->

控制结构

条件控制语句

Jinja2语法中的if语句跟Python中的if语句相似,后面的布尔值或者返回布尔值的表达式将决定代码中那个流程会被执行:

{% if user %}
Hello, {{ user }}
{% else %}
Hello, Stranger!
{% endif %}

for循环

我们可以在Jinja2中使用循环来迭代任何列表或者生成器函数

<ul>
{% for comment in comment %}
<li>{{ comment }}</li>
{% endfor %}
</ul>

循环和if语句可以组合使用

{% for post in posts if post.text %}
<div>
<h1>{{ post.title }}</h1>
<p>{{ post.text | safe }}</p>
</div>
{% endfor %}

在一个for循环块中你可以访问这些特殊的变量

变量 描述
loop.inde 当前循环迭代的次数(从1开始)
loop.index0 当前循环迭代的次数(从0开始)
loop.revindex 到循环结束需要迭代的次数(从1开始)
loop.revindex0 到循环结束需要迭代的次数(从0开始)
loop.frist 如果是第一次迭代,为True
loop.last 如果是最后一次迭代,为True
loop.length 序列中的项目数
loop.cycle 在一串序列间期取值的辅助函数

宏,类似Python代码中的函数

定义宏

{% macro input() %}
<input type="text"
name="username"
value=""
size="30"/>
{% endmacro %}

调用宏

{{ input() }}

定义带参数的宏

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

调用宏,并传递参数

{{ input(value='name',type='password',size=40)}}

把宏单独抽取出来,封装成html文件,其它模板中导入使用

文件名可以自定义macro.html

{% macro function() %}
<input type="text" name="username" placeholde="Username">
<input type="password" name="password" placeholde="Password">
<input type="submit">
{% endmacro %}

在其它模板文件中先导入,再调用

{% import 'macro.html' as func %}
{% func.function() %}

模板继承

在模板中,可能会遇到以下情况:

  • 多个模板具有完全相同的顶部和底部内容
  • 多个模板中具有相同的模板代码内容,但是内容中部分值不同
  • 多个模板中具有完全相同的html代码块内容

像遇到这种情况,可以使用Jinja2模板中的继承来进行实现

模板继承是为了重用模板中的公共内容.一般Web开发中,继承主要使用在网站的顶部菜单,底部.这些内容可以定义在父模板中,子模板直接继承,不需要重写

定义标签的内容

{% block top %} 

{% endblock%}
  • 相当于在父模板中挖个坑,当子模板继承父模板时候,可以进行填充
  • 子模板使用extends指令声明这个模板继承自哪个模板
  • 父模板中定义的块在子模板中被重新定义,在子模板中调用父模板的内容可以使用super()
from flask import Flask,render_template

app = Flask(__name__)

@app.route('/parent')
def parent():
return render_template('parent.html') @app.route('/child')
def child():
return render_template('child.html') if __name__ == '__main__':
app.run(debug=True)

父模板:parent.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head> <body>
<h2>我是头部</h2>
<hr> {# 将父模板中需要重写的内容使用block包含起来 #}
{% block content %}
<h2>我是父模板内容</h2>
{% endblock %}
<hr> <h2>我是底部</h2>
</body>
</html>

子模板:child.html

{# 1 使用extends关键字集成模板 #}
{% extends '06_one.html' %} {# 重写block #}
{% block content %} <h2>我是子模板内容</h2>
{% endblock %}
  • 模板继承使用时注意点:

    • 不支持多继承。
    • 为了便于阅读,在子模板中使用extends时,尽量写在模板的第一行。
    • 不能在一个模板文件中定义多个相同名字的block标签。
    • 当在页面中使用多个block标签时,建议给结束标签起个名字,当多个block嵌套时,阅读性更好。

包含(Include)

Jinja2模板中,除了宏和继承,还支持一种代码重用的功能,叫包含(Include)。它的功能是将另一个模板整个加载到当前模板中,并直接渲染。

示例:

include的使用

{% include 'hello.html' %}

包含在使用时,如果包含的模板文件不存在时,程序会抛出TemplateNotFound异常,可以加上ignore missing关键字。如果包含的模板文件不存在,会忽略这条include语句。

示例:

include的使用加上关键字ignore missing

{% include 'hello.html' ignore missing %}
  • 宏、继承、包含:

    • 宏(Macro)、继承(Block)、包含(include)均能实现代码的复用。
    • 继承(Block)的本质是代码替换,一般用来实现多个页面中重复不变的区域。
    • 宏(Macro)的功能类似函数,可以传入参数,需要定义、调用。
    • 包含(include)是直接将目标模板文件整个渲染出来。

过滤器

过滤器本质就是函数。

有时候我们不仅仅只是需要输出变量的值,我们还需要修改变量的显示,甚至格式化、运算等等,而在模板中是不能直接调用Python中的某些方法,那么这就用到了过滤器

使用方法:

  • 过滤器的使用方法为:变量名 | 过滤器.

    • {{ variable | filter_name(*args)}}
  • 如果没有任何参数传给过滤器,则可以把括号省略掉
    • {{variable | filter_name}}
  • 如:'',这个过滤器的作用:把变量variable的值首字母首字母转化为大写,其余字母转化为小写

链式调用

在Jinja2中,过滤器支持链式调用,示例如下:

{{'hello word' | reverse | upper}}

输出结果为:

DROW OLLEH

常见内建过滤器

  • safe:禁用转义

    <p>{{ '<em>hello</em>' | safe }}</p>
  • capitalize:把变量值的首字母转成大写,其余字母转小写

    <p>{{ 'hello' | capitalize }}</p>
  • lower:把值转成小写

    <p>{{ 'HELLO' | lower }}</p>
  • upper:把值转成大写

    <p>{{ 'hello' | upper }}</p>
  • title:把值中的每个单词的首字母都转成大写

    <p>{{ 'hello' | title }}</p>
  • reverse:字符串反转

    <p>{{ 'olleh' | reverse }}</p>
  • format:格式化输出

    <p>{{ '%s is %d' | format('name',17) }}</p>
  • striptags:渲染之前把值中所有的HTML标签都删掉

    <p>{{ '<em>hello</em>' | striptags }}</p>
  • truncate: 字符串截断

    <p>{{ 'hello every one' | truncate(9)}}</p>

列表操作

  • first:取第一个元素

    <p>{{ [1,2,3,4,5,6] | first }}</p>
  • last:取最后一个元素

    <p>{{ [1,2,3,4,5,6] | last }}</p>
  • length:获取列表长度

    <p>{{ [1,2,3,4,5,6] | length }}</p>
  • sum:列表求和

    <p>{{ [1,2,3,4,5,6] | sum }}</p>
  • sort:列表排序

    <p>{{ [6,2,3,1,5,4] | sort }}</p>

语句块过滤

{% filter upper %}
#一大堆文字#
{% endfilter %}

自定义过滤器

过滤器本质是函数,当模板内置的过滤器不能满足需求,可以自定义过滤器。自定义过滤器有两种方式实现。

  • 一种是通过Flask应用对象的add_template_filter方法
  • 通过装饰器来实现自定义过滤器

重要:自定义过滤器名称如果和内置过滤器重名,会覆盖内置的过滤器

需求:添加列表反转的过滤器

方式一

通过调用应用程序实例的 add_template_filter 方法实现自定义过滤器。该方法第一个参数是函数名,第二个参数是自定义的过滤器名称:

def do_listreverse(li):
# 通过原列表创建一个新列表
temp_li = list(li)
# 将新列表进行返转
temp_li.reverse()
return temp_li app.add_template_filter(do_listreverse,'lireverse')

方式二

用装饰器来实现自定义过滤器。装饰器传入的参数是自定义的过滤器名称。

@app.template_filter('lireverse')
def do_listreverse(li):
# 通过原列表创建一个新列表
temp_li = list(li)
# 将新列表进行返转
temp_li.reverse()
return temp_li

在html中使用该自定义过滤器

<br/> my_array 原内容:{{ my_array }}
<br/> my_array 反转:{{ my_array | lireverse }} <!--
运行结果:
my_array 原内容:[3, 4, 2, 1, 7, 9]
my_array 反转:[9, 7, 1, 2, 4, 3]
-->

完整代码:

from flask import Flask, render_template

app = Flask(__name__)

# 1.自定义列表反转函数
@app.template_filter('list_reverse')
# 方法二:使用装饰器
def list_reverse(list):
# list = []
list.reverse()
return list # 2.将自定义的函数添加到flask过滤器中
app.add_template_filter(list_reverse, 'list_reverse') @app.route('/')
def index():
list = [1, 3, 4, 5, 2] # 2,5,4,3,1
return render_template('test.html', list=list) if __name__ == '__main__':
app.run(debug=True)
<!--test.html-->

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h2>自定义过滤器</h2>
<br>
{{ list }}
<br>
{{ list | list_reverse }}
</body>
</html>

Flask模板渲染的更多相关文章

  1. Flask -- 静态文件 和 模板渲染

    静态文件 一般用于存放图片,样式文件(css, js等) 保存位置:包中或者文件所在目录创建一个 static 目录 访问:在应用中使用 /static/...即可访问 , 更好的方式是使用url_f ...

  2. flask模板的基本用法(定界符、模板语法、渲染模板),模板辅助工具(上下文、全局对象、过滤器、测试器、模板环境对象)

    flask模板 在动态web程序中,视图函数返回的HTML数据往往需要根据相应的变量(比如查询参数)动态生成. 当HTML代码保存到单独的文件中时,我们没法再使用字符串格式化或拼接字符串的当时在HTM ...

  3. Flask(1):基本示例、配置文件、路由、请求和响应、模板渲染

    Flask的特点: - pip install flask - 短小精悍.可扩展性强的 web框架 注意:上下文管理机制 - 依赖 wsgi:werkzeug Flask的简单示例: from fla ...

  4. Python Web Flask源码解读(三)——模板渲染过程

    关于我 一个有思想的程序猿,终身学习实践者,目前在一个创业团队任team lead,技术栈涉及Android.Python.Java和Go,这个也是我们团队的主要技术栈. Github:https:/ ...

  5. (4)Flask项目模板渲染初体验

    一.准备静态资源 将项目使用到的静态资源拷贝到static目录 二.创建前台首页html 创建templates/home/home.html页面,内容包含导航和底部版权两部分,中间内容区域为模板标签 ...

  6. Flask中的request模板渲染Jinja以及Session

    Flask中的request与django相似介绍几个常用的以后用的时候直接查询即可 1.request from flask import request(用之前先引用,与django稍有不同) r ...

  7. Flask 的模板渲染

    Flask 的模板渲染 渲染模板语言和django很像,都是用{{}},{%%} 注意点: 1 flask给模板传值,render_template("index.htm",use ...

  8. [Flask] Flask问题集(后端模板渲染项目)

    1.redirect和render_template的区别? redirect:重定向,会改变url render_template:模板渲染,用模板来渲染当前页,不会改变url 2.关于 'g' 对 ...

  9. Flask初级(六)flash模板渲染

    Project name :Flask_Plan templates:templates static:static 继续上篇的模板 我们已经可以静态调用模板,包括继承模板,保证了页面的一致性,但是我 ...

随机推荐

  1. C++学习03_引用

    基本使用 C++提供了给变量命名的机制,就是引用(Reference).引用是一种复合类型. //语法 数据类型 &name=data 注意,引用在定义时需要添加&,在使用时不能添加& ...

  2. 关于UE4音效的一些小问题

    前言 前几天实在忍受不了StarterContent默认音效的折磨,去网上翻罗了一下初中时很着迷的游戏<Bounce-Tales>的音效,在导入音效时出了点问题,特此说明一下解决方案,希望 ...

  3. MP的自动填充功能

    用来进行自动填充时间. 使用注解@TableTield(fill=FieldFill.insert)插入时进行性填充 使用注解@TableTield(fill=FieldFill.Update)更新时 ...

  4. 【转】前后端分离的项目如何部署发布到Linux

    前后端分离的项目如何部署发布到Linux 前期准备 1.服务器的基本配置信息2.本机远程连接服务器的工具(xshell.xftp或者mobaXterm等等,看你自己喜欢) 第一步:部署环境 1.安装j ...

  5. django之视图层和部分模板层

    视图层 小白必会三板斧(三个返回的都是HttpResponse对象,通过看源码,可以知道是内部实现) 1.HttpResponse # 返回字符串 2.render # 返回一个html页面 还可以给 ...

  6. HTTP协议COOKIE和SESSION有什么区别

    1.为什么会有COOKIE这种机制 首先一种场景, 在一个网站上面, 我发起一次请求,那服务器怎么知道我是谁?是谁发起的这次请求呢,  HTTP协议是无状态的协议, 浏览器的每一次请求,服务器都当做一 ...

  7. cf 1182 E - Product Oriented Recurrence

    当时脑残了, 不会写矩阵快速幂中更改的系数, 其实把他扔到矩阵里同时递推就好了 #include<cstdio> #include<algorithm> #include< ...

  8. 【LG5330】[SNOI2019]数论

    [LG5330][SNOI2019]数论 题面 洛谷 题目大意: 给定集合\(\mathbb {A,B}\) 问有多少个小于\(T\)的非负整数\(x\)满足:\(x\)除以\(P\)的余数属于\(\ ...

  9. [POI2014]RAJ(最短路,拓扑排序)

    对于一个点 \(x\) 如何求答案? 由于这个图是个有向无环图,可以先拓扑排序一遍,求出每个点的拓扑序,从起点到它的最长路 \(d2\),从它到终点的最长路 \(d1\).(我写代码是这么写的,注意顺 ...

  10. [LeetCode] 363. Max Sum of Rectangle No Larger Than K 最大矩阵和不超过K

    Given a non-empty 2D matrix matrix and an integer k, find the max sum of a rectangle in the matrix s ...