乐趣区

第二天在Flask-Web应用中使用模板

原文: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. 总结

学习完第二天的教程,我们掌握了如下技能:

  1. 知道什么是模板及为什么要使用模板
  2. 模板的基本用法
  3. 模板中如何使用条件语句
  4. 模板中如何使用循环语句
  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

退出移动版