原文:http://www.catonlinepy.tech/
声明:原创不易,未经许可,不得转载
1. 你将学会什么
通过学习第二天的内容,你将会对模板有所了解,并且知道为什么要使用模板,以及使用模板有什么好处。这一天的学习内容涉及到的代码都会托管到github上,猫姐再次强调,在学习本课内容时一定要自己尝试手敲代码,遇到问题再到github上去查看代码,如果实在不知道如何去解决问题,可以在日志下面留言说明具体情况。
2. 什么是模板
视图函数主要有两个作用,一个是处理业务逻辑,另一个是给用户返回相关内容。在大型应用中,如果把业务逻辑和返回响应内容放在一起的话,这样会增加代码的复杂度,并且也不好维护。所以模板它就承担了视图函数的另外一个作用:返回响应内容。这样就可以实现业务逻辑和响应内容的分离,将所有的html代码都存放到模板中,而视图函数中只需要专心处理好业务逻辑即可。
下面猫姐通过一个简单的例子来展示为什么要引入模板,以下是这个例子的代码组织结构:
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary$ tree
.
├── day2
│ ├── run.py
│ └── template_demo
│ ├── __init__.py
│ └── routes.py
└── README.md
首先来建立第二天的代码目录,与第一天的课程类似,先激活虚拟环境miao_venv,创建方法都是一样的:
# 进入到虚拟环境目录,激活虚拟环境
maojie@Thinkpad:~/flask-plan/$source miao_venv/bin/activate
# 再到flask-course-primary目录下创建第二天的课程day2目录
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary$ mkdir day2
# 进入day2目录
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary$ cd day2
# 新建template_demo目录
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day2$ mkdir template_demo
# 进入到template_demo目录
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day2$ cd template_demo/
# 在template_demo目录中新建__init__.py文件
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day2/template_demo$ touch __init__.py
# 在template_demo包中新建routes.py路由文件
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day2/template_demo$ touch routes.py
# 在day2目录下新建run.py文件
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day2/$ touch run.py
在template_demo包的__init__.py中输入如下代码:
# 以下是__init__.py文件中的代码,我们逐行进行解释
from flask import Flask # 从flask包中导入Flask类
app = Flask(__name__) # 通过Flask类创建一个app实例
from template_demo import routes # 从template_demo包中导入routes文件里的所有代码
在routes.py文件中输入如下代码,包括响应内容中的HTML代码:
# 从template_demo包中导入app实例
from template_demo import app
@app.route('/')
def index():
user = {'username':'猫姐'} # 建立一个user字典
# 返回HTML格式的响应内容
return '''
<html>
<head>
<title>Home Page-模板的使用-喵星在线</title>
</head>
<body>
<h1>Hello,''' + user['username'] + '''!</h1>
</body>
</html>'''
在第一课中,视图函数返回的字符串是“你好,喵星在线”,而今天的课程,通过扩展,return 语句中呈现了完整的HTML代码。如果大家对HTML语言不熟悉,可以在w3school在线教程中进行学习。
最后在day2目录下run.py文件中输入如下代码:
from template_demo import app # 从template_demo包中导入app实例
if __name__ == "__main__":
app.run(debug=True) # app实例调用自己的run函数
# 解释:debug=True,每次代码有改动时,后台会自动检测到,避免自己每次停止、重启后台程序
用第一课运行程序的方法(python run.py),将程序运行起来,然后在浏览器中打开网址 http://localhost:5000/,查看结果:
这样应用就运行起来了。大家有没有发现,如果我后面还想扩展其他功能,index视图函数里面的代码也会相应的变多,并且应用的视图函数和关联的URL也会相应的增加。如果我还想将HTML里面的布局更改一下的话,那我不得不更改每个视图函数里面的HTML标签,这样是不利于长久管理以及应用的扩张。
所以,这里就出来了模板的概念,模板有助于实现业务逻辑和响应内容之间的分离,是实际项目开发中必须使用的一个技术。在Flask中,模板文件(即html文件)需要单独存放在包内的templates目录下。
3. 使用模板
在template_demo包中新建templates目录,用来存放模板文件:
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day2/template_demo$ mkdir templates
创建模板文件index.html,并输入HTML代码:
# 创建模板文件index.html (下面是使用touch命令创建的,大家也可以在ide集成开发环境中创建该文件)
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day2/template_demo/templates$ touch index.html
# 在index.html中输入如下代码,这里title,html_user变量是从视图函数中传进来的
<html>
<head>
<title>{{ title }}-模板的使用-喵星在线</title>
</head>
<body>
<h1>Hello,{{ html_user.username }}!</h1>
</body>
</html>
在上面的HTML代码中,唯一值得关注的就是{{ ... }}里面的内容,这些变量都是从视图函数中传递进来的。
要渲染模板文件,还需要从Flask框架中导入render_template()这个函数,如下:
# 在routes.py文件中,从flask库中导入render_template类
from flask import render_template
在视图函数中调用render_template时,需要传入模板的文件名以及模板参数的变量列表。视图函数中进行如下操作,便可使用模板了:
# routes.py文件中输入如下代码
from flask import render_template # 从flask库中导入render_template对象
from template_demo import app # 从template_demo包中导入app实例
@app.route('/')
def index():
user = {'username':'猫姐'} # 建立一个user字典
return render_template('index.html', title='HomePage', html_user=user)
在render_template函数中,index.html表示的是模板的文件名。title,html_user表示在模板文件中需要使用的变量。user表示是视图函数中的user变量,user变量赋值给html_user变量,在模板中渲染的就是user变量的值了。这样,routes.py文件中的代码就好看多了,从而就实现了业务代码和前端html代码分离的效果,而且也更便于管理日后越发复杂的html代码。
用同样的方式运行程序,效果应用和没有使用模板的情况是一样的,如下图
4. 模板的其它知识点
下面我们介绍一下模板的其它常用知识点,主要包括模板中if条件语句的使用,for循环语句的使用以及模板的继承方法。
4.1 模板中的if条件语句的使用
说到模板中的条件语句,这里不得不说说Jinja2的概念。它是python下被广泛应用的模板引擎,是一种被设计自动生成文档的简单格式。在模板语言中,需要把变量传给模板,然后替换成模板特定位置上的占位变量名。它的使用方法很简单,需要用到两对大的花括号,{{ ... }},它里面传入的是变量名。
而Jinja2的条件语句,使用方法也很简单,它用到的是一对花括号,里面再加两个百分号,像这样{% %}。然后里面可以写if,else,for等,但是以if,for开头,必须有闭合if,for的标签。如下所示:
# jinja2中 if控制语句的使用
{% if title %}
{{ ... }}
{% else %}
{{ ... }}
{% endfor %}
# jinja2中 for控制语句的使用
{% for i in username %}
{{ ... }}
{% endfor %}
下面是在模板index.html文件添加一个条件语句的示例:
<html>
<head>
{% if title %}
<title>{{ title }} -模板的使用-喵星在线</title>
{% else %}
<title>模板的使用-喵星在线</title>
{% endif %}
</head>
<body>
<h1>Hello, {{ html_user.username }}!</h1>
</body>
</html>
如果视图函数给模板传递了title参数,那么它就会走if语句,如果没有传递参数,则会走else语句,而不是显示一个空的标题。在本例中,没有给render_template函数的title参数传入值,所以它会走else语句,效果如下图所示:
4.2 模板中的循环
要理解Jinja2中是如何在模板中使用循环的,我们可以在路由函数中增加一些其它的信息,如下面使用posts列表变量保存了一些假的日志信息,并将posts变量传递给了模板文件中将使用的htm_posts变量:
from flask import render_template
from template_demo import app
@app.route('/')
def index():
user = {'username': '猫姐'}
# 日志由一个列表组成,其中里面包含两个字典,里面各有author和content字段
posts = [
{
'author': {'username': '猫姐'},
'content': 'This day is Beautiful day!'
},
{
'author': {'username': '猫哥'},
'content': 'The flower is beautiful!'
}
]
return render_template('index.html', title='HomePage', html_user=user, html_posts=posts)
在index.html模板文件中,通过上面介绍的for循环语法,完成对htm_posts列表变量中每一篇日志的渲染:
<!DOCTYPE html>
<html lang="en">
<head>
{% if title %}
<title>{{ title }} -模板的使用-喵星在线</title>
{% else %}
<title>模板的使用-喵星在线</title>
{% endif %}
</head>
<body>
<h1>Hello, {{ html_user.username }}!</h1>
{% for post in html_posts %} <!--for循环开始-->
<div>
<p>
{{ post.author.username }} says:<b>{{ post.content }}</b>
</p>
</div>
{% endfor %} <!-- for循环结束-->
</body>
</html>
打开浏览器URL,效果如下图所示:
4.3 模板的继承
我们在写一个web应用时,随着里面的功能增多,代码也会相应的变多,这时可能会有一些重复的HTML代码,为了去除大量重复的代码,这时候出现了模板继承的概念。它也是Jinja2的特性,它的特点就是将模板中相同的部分代码转移到一个基模板中,后面其它模板要使用的时候,只需要继承基模板就可以了。
在template_demo/templates目录下,新建layout.html文件,然后在layout.html中写入如下代码:
# 在templates目录下新建layout.html文件
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day2/templates$ touch layout.html
# layout.html文件中写入如下代码:
<html>
<head>
{% if title %}
<title>{{ title }} - 模板的使用-喵星在线</title>
{% else %}
<title>模板的使用-喵星在线</title>
{% endif %}
</head>
<body>
{% block content %}
{% endblock %}
</body>
</html>
在这个layout.html模板中,使用block控制块来确定子模板插入代码的位置。子模板通过引用block可以在里面添加自己想要的内容。
下面index.html文件,可以直接继承layout.html文件中的内容,而无需重复实现这段代码,这样在可以简化index.html里面的内容:
# index.html中改为如下内容
{% extends "layout.html" %} # 继承基模板里面的内容
{% block content %} # 重新填写content块的内容
<h1>Hi, {{ html_user.username }}!</h1>
{% for post in html_posts %}
<div>
<p>{{ post.author.username }} says: <b>{{ post.content }}</b></p>
</div>
{% endfor %}
{% endblock %}
打开浏览器的URL,效果如下图所示:
5. 总结
学习完第二天的教程,我们掌握了如下技能:
- 知道什么是模板及为什么要使用模板
- 模板的基本用法
- 模板中如何使用条件语句
- 模板中如何使用循环语句
- 模板中如何继承基模板
第三天的内容,我们将会带领大家一起了解什么是表单,表单如何创建,第二天的内容就到这里,喜欢的同学们可以在下面点赞留言,或是访问我的博客地址:http://www.catonlinepy.tech/ 加入我们的QQ群进一步交流学习!
6. 代码的获取
大家可以到github上获取今天教程中的所有代码:https://github.com/miaojie19/...
具体下载代码的命令如下:
# 使用git命令下载flask-course-primary仓库所有的代码
git clone https://github.com/miaojie19/flask-course-primary.git
# 下载完成后,进入day2目录下面,即可看到今天的代码
cd flask-course-primary
cd day2
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。