第三章 Flask day1

模板

在动态Web程序中,视图函数返回的HTML数据往往需要根据相应的变量(比如查询参数)动态生成。
当HTML代码保存到单独的文件中时,就无法使用字符串格式化或拼接字符串的方式来在HTML代码中插入变量,这时需要使用模板引擎(template engine)。
借助模板引擎,我们可以在HTML文件中使用特殊的语法来标记出变量,这类包含固定内容和动态部分的可重用文件称为模板(template)。
模板引擎的作用就是读取并执行模板中的特殊语法标记,并根据传入的数据将变量替换为实际值,输出最终的HTML页面,这个过程被称为渲染(rendering)
Flask默认使用的模板引擎是Jinja2

模板的基本用法

创建虚拟数据

假设我们需要编写一个用户的电影清单页面,类似IMDB的watchlist页面的简易版,模板中要显示用户信息以及用户收藏的电影列表,包含电影的名字和年份。我们首先创建一些虚拟数据用于测试显示效果:

user = { 
	'username': 'Grey Li', 
	'bio': 'A boy who loves movies and music.', 
}
movies = [ 
	{'name': 'My Neighbor Totoro', 'year': '1988'}, 
	{'name': 'Three Colours trilogy', 'year': '1993'}, 
	{'name': 'Forrest Gump', 'year': '1994'}, 
	{'name': 'Perfect Blue', 'year': '1997'}, 
	{'name': 'The Matrix', 'year': '1999'}, 
	{'name': 'Memento', 'year': '2000'}, 
	{'name': 'The Bucket list', 'year': '2007'}, 
	{'name': 'Black Swan', 'year': '2010'}, 
	{'name': 'Gone Girl', 'year': '2014'}, 
	{'name': 'CoCo', 'year': '2017'}, 
]

创建一个电影清单模板

我们在templates目录下创建一个watchlist.html作为模板文件,然后使用Jinja2支持的语法在模板中操作这些变量

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{ user.username }}'s Watchlist</title>
</head>
<body>
{# html的注释好像可以这样打 #}
{# 这是一个链接 名字是Return  &larr应该是蓝色? 跳转去url是index的页面#}
<a href="{{ url_for('index') }}">&larr; Return</a>
{# 应该是一个ifelse语句,如果判断用户的bio(就是签名)是否存在#}
<h2>{{ user.username }}</h2>
{% if user.bio %}
    <i>{{ user.bio }}</i>
{% else %}
    <i>This user has not provided a bio.</i> {% endif %}
{# 下面是电影清单 #}
<h5>{{ user.username }}'s Watchlist ({{ movies|length }}):</h5>
{# <ul> 标签用来定义无序列表 #}
<ul>
    {% for movie in movies %}
        {# <li> 标签定义列表项,有序列表和无序列表中都使用 <li> 标签。 #}
        <li>{{ movie.name }} - {{ movie.year }}</li>
    {% endfor %}
</ul>
</body>
</html>

在模板中添加Python语句和表达式时,需要使用特定的定界符把它们标示出来。
watchlist.html中涉及的模板语法,会在下面逐一介绍。

定界符

首先,可以在上面的代码中看到Jinja2里常见的三种定界符

  1. 语句:比如说if判断,for判断
    {% ... %}

  2. 表达式:比如字符串、变量、函数调用等:
    {{ ... }}

  3. 注释
    {{#这里是注释#}}

另外,在模板中,Jinja2支持使用“.”获取变量的属性,比如user字典中的username键值通过“.”获取,即user.username,在效果上等同于 user[‘username’]。

模板语法

Jinja2提供了多种控制结构来控制模板的输出,其中for和if是最常用的两种。在Jinja2里,语句使用{%…%}标识,尤其需要注意的是,在语句结束的地方,我们必须添加结束标签:

{% if user.bio %}
    <i>{{ user.bio }}</i>
{% else %}
    <i>This user has not provided a bio.</i>
{% endif %}

末尾的{%endif%}用来声明if语句的结束,这一行不能省略。

<ul>
    {% for movie in movies %}
        {# <li> 标签定义列表项,有序列表和无序列表中都使用 <li> 标签。 #}
        <li>{{ movie.name }} - {{ movie.year }}</li>
    {% endfor %}
</ul>

和在Python里一样,for语句用来迭代一个序列,和其他语句一样,你需要在for循环的结尾使用endfor标签声明for语句的结束。
在for循环内,Jinja2提供了多个特殊变量,常用的循环变量 如表所示
在这里插入图片描述

渲染模板

渲染一个模板,就是执行模板中的代码,并传入所有在模板中使用的变量,渲染后的结果就是我们要返回给客户端的HTML响应。
在视图函数中渲染模板时,我们并不直接使用Jinja2提供的函数,而是使用 Flask提供的渲染函数render_template()

@app.route('/watchlist')
def watchlist():
    return render_template('watchlist.html',
    						user=user, movies=movies)

那么此时,根据我们传入的虚拟数据,render_template()渲染后返回的 HTML数据如下所示:

<!DOCTYPE html> 
<html lang="en"> 
<head>
	<meta charset="utf-8"> 
	<title>Grey Li's Watchlist</title> 
</head> 
<body> 
<a href="/">&larr; Return</a> 
<h2>Grey Li</h2> 
<i>A boy who loves movies and music.</i> 
<h5>Grey Li's Watchlist (10):</h5> 
<ul>
	<li>My Neighbor Totoro - 1988</li> 
	<li>Three Colours trilogy - 1993</li> 
	<li>Forrest Gump - 1994</li> 
	<li>Perfect Blue - 1997</li> 
	<li>The Matrix - 1999</li> 
	<li>Memento - 2000</li> 
	<li>The Bucket list - 2007</li> 
	<li>Black Swan - 2010</li> 
	<li>Gone Girl - 2014</li> 
	<li>CoCo - 2017</li>
</ul>
</body>
</html>

在这里插入图片描述注意:/index必须写一个界面才能运行成功

总代码

app.py

from flask import Flask,render_template
app = Flask(__name__)

@app.route('/')
def Hello_world():
    return 'This is main interface'
user = {
	'username': 'Grey Li',
	'bio': 'A boy who loves movies and music.',
}
movies = [
	{'name': 'My Neighbor Totoro', 'year': '1988'},
	{'name': 'Three Colours trilogy', 'year': '1993'},
	{'name': 'Forrest Gump', 'year': '1994'},
	{'name': 'Perfect Blue', 'year': '1997'},
	{'name': 'The Matrix', 'year': '1999'},
	{'name': 'Memento', 'year': '2000'},
	{'name': 'The Bucket list', 'year': '2007'},
	{'name': 'Black Swan', 'year': '2010'},
	{'name': 'Gone Girl', 'year': '2014'},
	{'name': 'CoCo', 'year': '2017'},
]
@app.route('/watchlist')
def watchlist():
    return render_template('watchlist.html', user=user, movies=movies)
@app.route('/index')
def index():
    return "Good Job"

if __name__ == '__main__':
    app.run()

watchlist,html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{{ user.username }}'s Watchlist</title>
</head>
<body>
{# html的注释好像可以这样打 #}
{# 这是一个链接 名字是Return  &larr是左箭头 跳转去url是index的页面#}
<a href="{{ url_for('index') }}">&larr; Return</a>
{# 应该是一个ifelse语句,如果判断用户的bio(就是签名)是否存在#}
<h2>{{ user.username }}</h2>
{% if user.bio %}
    <i>{{ user.bio }}</i>
{% else %}
    <i>This user has not provided a bio.</i>
{% endif %}
{# 下面是电影清单 #}
<h5>{{ user.username }}'s Watchlist ({{ movies|length }}):</h5>
{# <ul> 标签用来定义无序列表 #}
<ul>
    {% for movie in movies %}
        {# <li> 标签定义列表项,有序列表和无序列表中都使用 <li> 标签。 #}
        <li>{{ movie.name }} - {{ movie.year }}</li>
    {% endfor %}
</ul>
</body>
</html>

模板辅助工具

为方便测试模板辅助工具,于是创建了一个基本的index.html 并在主页面写

from flask import render_template 
@app.route('/') 
def index(): 
	return render_template('index.html')

上下文

模板上下文包含了很多变量,其中包括我们调用 render_template()函数时手动传入的变量以及Flask默认传入的变量。
除了渲染时传入变量,也可以在模板中定义变量,使用set标签:

{% set navigation = [('/', 'Home'), ('/about', 'About')] %}

也可以将一部分模板数据定义为变量,使用set和endset标签声明 开始和结束:

{% set navigation %} 
	<li><a href="/">Home</a> 
	<li><a href="/about">About</a> 
{% endset %}

如果传入的是’/’,那就名字变为Home
如果传入的是’/home‘,那就名字变为About

自定义上下文

如果多个模板都需要使用同一变量,那么比起在多个视图函数中重复传入,更好的方法是能够设置一个模板全局变量。
Flask提供了一个 app.context_processor装饰器,可以用来注册模板上下文处理函数,它可以帮我们完成统一传入变量的工作。
模板上下文处理函数需要返回一个包含变量键值对的字典。

@app.context_processor 
def inject_foo(): 
	foo = 'I am foo.' 
	return dict(foo=foo) # 等同于return {'foo': foo}

当我们调用render_template()函数渲染任意一个模板时,所有使用app.context_processor装饰器注册的模板上下文处理函数(包括Flask内 置的上下文处理函数)都会被执行,这些函数的返回值会被添加到模板 中,因此我们可以在模板中直接使用foo变量。
和在render_template()函数中传入变量也类似,除了字符串、列表 等数据结构,你也可以传入函数、类或类实例。

除了使用app.context_processor装饰器,也可以直接将其作为方法调用,传入模板上下文处理函数:

def inject_foo(): 
	foo = 'I am foo.' 
	return dict(foo=foo) 
app.context_processor(inject_foo)

使用lambda可以简化为:app.context_processor(lambda: dict(foo='I am foo.'))

全局对象

全局对象是指在所有的模板中都可以直接使用的对象,包括在模板中导入的模板,后面我们会详细介绍导入的概念。

  1. 内置全局函数
    在这里插入图片描述
    在这里插入图片描述
    Flask除了把g、session、config、request对象注册为上下文变量,也 将它们设为全局变量,因此可以全局使用。
  2. 自定义全局函数:除了使用app.context_processor注册模板上下文处理函数来传入函数,我们也可以使用app.template_global装饰器直接将函数注册为模板全局函数。
@app.template_global() 
def bar(): 
	return 'I am bar.'

app.template_global()仅能用于注册全局函数,后面会介绍如何注册全局变量。

过滤器

在Jinja2中,过滤器(filter)是一些可以用来修改和过滤变量值的特殊函数,过滤器和变量用一个竖线隔开,需要参数的过滤器可以像函数一样使用括号传递。

{{ name|title }}

这会将name变量的值标题化,相当于在Python里调用 name.title()
再比如,我们在本章开始的示例模板watchlist.html中使用length获取movies列表的长度,类似于在Python中调用 len(movies):

{{ movies|length }}

另一种用法是将过滤器作用于一部分模板数据,使用filter标签和 endfilter标签声明开始和结束。比如,下面使用upper过滤器将一段文字转换为大写:

{% filter upper %} 
	This text becomes uppercase. 
{% endfilter %}

Jinja2常用过滤器

在这里插入图片描述
在这里插入图片描述
在使用过滤器时,列表中过滤器函数的第一个参数表示被过滤的变量值(value)或字符串(s),即竖线符号左侧的值,其他的参数可以通过添加括号传入。
另外,过滤器可以叠加使用,下面的示例为name变量设置默认值, 并将其标题化:

<h1>Hello, {{ name|default('陌生人')|title }}!</h1>

自定义过滤器

使用app.template_filter()装饰器可以注册自定义过滤器

from flask import Markup 
@app.template_filter() 
def musical(s): 
	return s + Markup(' &#9835;')

和注册全局函数类似,可以在app.template_filter()中使用name关键字设置过滤器的名称,默认会使用函数名称。
过滤器函数需要接收被处理的值作为输入,返回处理后的值。过滤器函数接收s作为被过滤的变量值,返回处理后的值。
我们创建的musical过滤器会在被过滤的变量字符后面添加一个音符(single bar note)图标,因为音符通过HTML 实体&#9835;表示,我们使用Markup类将它标记为安全字符。在使用时和其他过滤器用法相同

{{ name|musical }}

测试器

在Jinja2中,测试器(Test)是一些用来测试变量或表达式,返回布尔值(True或False)的特殊函数。
比如,number测试器用来判断一个变量或表达式是否是数字,我们使用is连接变量和测试器:

{% if age is number %}
	{{ age * 365 }} 
{% else %} 
	无效的数字。 
{% endif %}

内置测试器

在这里插入图片描述
在使用测试器时,is的左侧是测试器函数的第一个参数(value), 其他参数可以添加括号传入,也可以在右侧使用空格连接,以sameas为例

{% if foo is sameas(bar) %}...
等同于
{% if foo is sameas bar %}...

自定义测试器

和过滤器类似,我们可以使用Flask提供的app.template_test()装饰 器来注册一个自定义测试器。在示例程序中,我们创建了一个没有意义 的baz过滤器,仅用来验证被测值是否为baz

@app.template_test()
def baz(n): 
	if n == 'baz': return True 
	return False
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
4S店客户管理小程序-毕业设计,基于微信小程序+SSM+MySql开发,源码+数据库+论文答辩+毕业论文+视频演示 社会的发展和科学技术的进步,互联网技术越来越受欢迎。手机也逐渐受到广大人民群众的喜爱,也逐渐进入了每个用户的使用。手机具有便利性,速度快,效率高,成本低等优点。 因此,构建符合自己要求的操作系统是非常有意义的。 本文从管理员、用户的功能要求出发,4S店客户管理系统的功能模块主要是实现管理员服务端;首页、个人心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理,用户客户端:首页、车展、新闻头条、我的。门店客户端:首页、车展、新闻头条、我的经过认真细致的研究,精心准备和规划,最后测试成功,系统可以正常使用。分析功能调整与4S店客户管理系统实现的实际需求相结合,讨论了微信开发者技术与后台结合java语言和MySQL数据库开发4S店客户管理系统的使用。 关键字:4S店客户管理系统小程序 微信开发者 Java技术 MySQL数据库 软件的功能: 1、开发实现4S店客户管理系统的整个系统程序; 2、管理员服务端;首页、个人心、用户管理、门店管理、车展管理、汽车品牌管理、新闻头条管理、预约试驾管理、我的收藏管理、系统管理等。 3、用户客户端:首页、车展、新闻头条、我的 4、门店客户端:首页、车展、新闻头条、我的等相应操作; 5、基础数据管理:实现系统基本信息的添加、修改及删除等操作,并且根据需求进行交流信息的查看及回复相应操作。
现代经济快节奏发展以及不断完善升级的信息化技术,让传统数据信息的管理升级为软件存储,归纳,集处理数据信息的管理方式。本微信小程序医院挂号预约系统就是在这样的大环境下诞生,其可以帮助管理者在短时间内处理完毕庞大的数据信息,使用这种软件工具可以帮助管理人员提高事务处理效率,达到事半功倍的效果。此微信小程序医院挂号预约系统利用当下成熟完善的SSM框架,使用跨平台的可开发大型商业网站的Java语言,以及最受欢迎的RDBMS应用软件之一的MySQL数据库进行程序开发。微信小程序医院挂号预约系统有管理员,用户两个角色。管理员功能有个人心,用户管理,医生信息管理,医院信息管理,科室信息管理,预约信息管理,预约取消管理,留言板,系统管理。微信小程序用户可以注册登录,查看医院信息,查看医生信息,查看公告资讯,在科室信息里面进行预约,也可以取消预约。微信小程序医院挂号预约系统的开发根据操作人员需要设计的界面简洁美观,在功能模块布局上跟同类型网站保持一致,程序在实现基本要求功能时,也为数据信息面临的安全问题提供了一些实用的解决方案。可以说该程序在帮助管理者高效率地处理工作事务的同时,也实现了数据信息的整体化,规范化与自动化。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值