2

原文: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/,查看结果:

clipboard.png

这样应用就运行起来了。大家有没有发现,如果我后面还想扩展其他功能,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代码。

用同样的方式运行程序,效果应用和没有使用模板的情况是一样的,如下图

clipboard.png

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语句,效果如下图所示:

clipboard.png

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,效果如下图所示:

clipboard.png

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,效果如下图所示:

clipboard.png

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

图片描述


猫姐_游戏编程
56 声望17 粉丝

😸猫姐,211硕士,定居成都的荆州人,5年IT生涯,教大家做益智小游戏,快乐学编程