如何在Flask应用程序中使用模板

来自菜鸟教程
跳转至:导航、​搜索

作为 Write for DOnations 计划的一部分,作者选择了 Free and Open Source Fund 来接受捐赠。

介绍

Flask 是一个轻量级的 Python Web 框架,它为使用 Python 语言创建 Web 应用程序提供了有用的工具和功能。

在开发 Web 应用程序时,将 业务逻辑表示逻辑 分开是很重要的。 业务逻辑处理用户请求并与数据库对话以构建适当的响应。 呈现逻辑 是数据如何呈现给用户,通常使用 HTML 文件来构建响应网页的基本结构,并使用 CSS 样式来设置 HTML 组件的样式。 例如,在社交媒体应用程序中,您可能有一个用户名字段和一个密码字段,只有在用户未登录时才能显示。 如果用户已登录,则会显示一个注销按钮。 这就是表示逻辑。 如果用户输入他们的用户名和密码,您可以使用 Flask 执行业务逻辑:您从请求中提取数据(用户名和密码),如果凭据正确则登录用户或以错误消息响应。 错误消息的显示方式将由表示逻辑处理。

在 Flask 中,您可以使用 Jinja 模板语言来呈现 HTML 模板。 template 是一个可以包含固定和动态内容的文件。 当用户从您的应用程序(例如索引页面或登录页面)请求某些内容时,Jinja 允许您使用 HTML 模板进行响应,您可以在其中使用标准 HTML 中不可用的许多功能,例如变量、[X237X ] 语句、for 循环、过滤器和模板继承。 这些功能使您可以高效地编写易于维护的 HTML 页面。 Jinja 还自动转义 HTML 以防止 Cross-Site Scripting (XSS) 攻击。

在本教程中,您将构建一个呈现多个 HTML 文件的小型 Web 应用程序。 您将使用变量将数据从服务器传递到模板。 模板继承将帮助您避免重复。 您将在诸如条件和循环之类的模板中使用逻辑,使用过滤器来修改文本,并使用 Bootstrap 工具包 来设置应用程序的样式。

先决条件

第 1 步 — 渲染模板并使用变量

确保你已经激活了你的环境并安装了 Flask,然后你就可以开始构建你的应用程序了。 第一步是在索引页面上显示一条欢迎访问者的消息。 您将使用 Flask 的 render_template() 辅助函数来提供 HTML 模板作为响应。 您还将看到如何将变量从应用程序端传递到模板。

首先,在您的 flask_app 目录中,打开一个名为 app.py 的文件进行编辑。 使用 nano 或您喜欢的文本编辑器:

nano app.py

app.py 文件中添加以下代码:

烧瓶应用程序/app.py

from flask import Flask, render_template

app = Flask(__name__)


@app.route('/')
def hello():
    return render_template('index.html')

保存并关闭文件。

在此代码块中,您从 flask 包中导入 Flask 类和 render_template() 函数。 您使用 Flask 类来创建名为 app 的 Flask 应用程序实例。 然后使用 app.route() 装饰器定义一个名为 hello()视图函数 (这是一个返回 HTTP 响应的 Python 函数),它将常规函数转换为视图函数. 此视图函数使用 render_template() 函数来渲染一个名为 index.html 的模板文件。

接下来,您必须在 flask_app 目录中名为 templates 的目录中创建 index.html 模板文件。 Flask 在 templates 目录 中查找模板,该目录名为 templates,因此名称很重要。 确保您在 flask_app 目录中并运行以下命令来创建 templates 目录:

mkdir templates

接下来,在 templates 目录中打开一个名为 index.html 的文件进行编辑。 这里的名称 index.html 不是标准要求的名称; 如果需要,您可以将其称为 home.htmlhomepage.html 或其他任何名称:

nano templates/index.html

index.html 文件中添加以下 HTML 代码:

flask_app/templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>FlaskApp</title>
</head>
<body>
    <h1>Hello World!</h1>
    <h2>Welcome to FlaskApp!</h2>
</body>
</html>

在这里,您设置了标题,添加了 Hello World! 消息作为 H1 标题,并创建了 Welcome to FlaskApp! 消息作为 H2 标题。

保存并关闭文件。

在激活虚拟环境的 flask_app 目录中,使用 FLASK_APP 环境变量告诉 Flask 应用程序(在您的情况下为 app.py),并设置 [ X191X] 环境变量到 development 以在开发模式下运行应用程序并访问调试器。 使用以下命令执行此操作(在 Windows 上,使用 set 而不是 export):

export FLASK_APP=app
export FLASK_ENV=development

然后,使用 flask run 命令运行应用程序:

flask run

在开发服务器运行的情况下,使用浏览器访问以下 URL:

http://127.0.0.1:5000/

您会看到页面的标题设置为 FlaskApp,并且两个标题都呈现为 HTML。

在 Web 应用程序中,您经常需要将数据从应用程序的 Python 文件传递到 HTML 模板。 为了演示如何在此应用程序中执行此操作,您将包含当前 UTC 日期和时间的变量传递给索引模板,并且您将在模板中显示该变量的值。

保持服务器运行,并在新终端中打开 app.py 文件进行编辑:

nano app.py

从 Python 标准库中导入 datetime 模块并编辑 index() 函数,使文件如下所示:

烧瓶应用程序/app.py

import datetime
from flask import Flask, render_template

app = Flask(__name__)


@app.route('/')
def hello():
    return render_template('index.html', utc_dt=datetime.datetime.utcnow())

保存并关闭文件。

在这里,您导入了 datetime 模块并将名为 utc_dt 的变量传递给 index.html 模板,其值为 datetime.datetime.utcnow(),即当前的 UTC 日期和时间.

接下来,要在索引页面上显示变量的值,请打开 index.html 文件进行编辑:

nano templates/index.html

编辑该文件,如下所示:

flask_app/templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>FlaskApp</title>
</head>
<body>
    <h1>Hello World!</h1>
    <h2>Welcome to FlaskApp!</h2>
    <h3>{{ utc_dt }}</h3>
</body>
</html>

保存并关闭文件。

您添加了一个带有特殊 模板:... 分隔符的 H3 标题,以打印 utc_dt 变量的值。

打开浏览器并访问索引页面:

http://127.0.0.1:5000/

您将看到类似于下图的页面:

您现在已经在 Flask 应用程序中创建了一个带有 HTML 模板的索引页面,呈现了一个模板,并传递并显示了一个变量值。 接下来,您将通过使用模板继承来避免代码重复。

第 2 步 — 使用模板继承

在此步骤中,您将制作一个基本模板,其中包含可与其他模板共享的内容。 您将编辑索引模板以从基本模板继承。 然后,您将创建一个新页面作为应用程序的 About 页面,用户可以在其中找到有关您的应用程序的更多信息。

基本模板 包含通常在所有其他模板之间共享的 HTML 组件,例如应用程序的标题、导航栏和页脚。

首先,在模板目录中打开一个名为 base.html 的新文件进行编辑:

nano templates/base.html

base.html 文件中写入以下代码:

flask_app/templates/base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %} {% endblock %} - FlaskApp</title>
    <style>
        nav a {
            color: #d64161;
            font-size: 3em;
            margin-left: 50px;
            text-decoration: none;
        }
    </style>
</head>
<body>
    <nav>
        <a href="#">FlaskApp</a>
        <a href="#">About</a>
    </nav>
    <hr>
    <div class="content">
        {% block content %} {% endblock %}
    </div>
</body>
</html>

保存并关闭文件。

此文件中的大部分代码是标准 HTML、标题、导航链接的一些样式、带有两个链接的导航栏,一个用于索引页面,一个用于尚未创建的关于页面,还有一个 [X206X ] 用于页面的内容。 (链接还没有工作;下一步将演示如何在页面之间链接)。

但是,以下突出显示的部分特定于 Jinja 模板引擎:

  • {% block title %} {% endblock %}:一个 block,用作标题的占位符。 您稍后将在其他模板中使用它来为应用程序中的每个页面提供自定义标题,而无需每次都重写整个 <head> 部分。
  • {% block content %} {% endblock %}:另一个块将被内容替换,具体取决于将覆盖它的 子模板 (继承自 base.html 的模板)。

现在您已经有了一个基本模板,您可以使用继承来利用它。 打开index.html文件:

nano templates/index.html

然后将其内容替换为以下内容:

flask_app/templates/index.html

{% extends 'base.html' %}

{% block content %}
    <h1>{% block title %} Index {% endblock %}</h1>
    <h1>Hello World!</h1>
    <h2>Welcome to FlaskApp!</h2>
    <h3>{{ utc_dt }}</h3>
{% endblock %}

在这里,您使用 {% extends %} 标记从 base.html 模板继承。 然后,您可以通过将基本模板中的 content 块替换为前面代码块中 content 块中的内容来扩展它。

此内容块包含一个 <h1> 标记,标题块内带有文本 Index,这反过来将 base.html 模板中的原始 title 块替换为文本 Index 以便完整的标题变为 Index - FlaskApp。 这样,您可以避免重复两次相同的文本,因为它既可以用作页面的标题,也可以用作从基本模板继承而来的导航栏下方的标题。

然后你还有几个标题:一个带有文本 Hello World!<h1> 标题、一个 <h2> 标题和一个 <h3> 标题,其中包含 [ X157X] 变量。

模板继承使您能够重用您在其他模板(本例中为 base.html)中的 HTML 代码,而无需在每次需要时重复。

保存并关闭文件并刷新浏览器上的索引页面。 该页面将如下所示:

接下来,您将创建“关于”页面。 打开 app.py 文件添加新路由:

nano app.py

在文件末尾添加以下路由:

烧瓶应用程序/app.py

# ...
@app.route('/about/')
def about():
    return render_template('about.html')

在这里,您使用 app.route() 装饰器创建一个名为 about() 的视图函数。 在其中,您返回以 about.html 模板文件名作为参数调用 render_template() 函数的结果。

保存并关闭文件。

打开一个名为 about.html 的模板文件进行编辑:

nano templates/about.html

将以下代码添加到文件中:

flask_app/templates/about.html

{% extends 'base.html' %}

{% block content %}
    <h1>{% block title %} About {% endblock %}</h1>
    <h3>FlaskApp is a Flask web application written in Python.</h3>
{% endblock %}

在这里,您使用 extends 标记从基本模板继承,将基本模板的 content 块替换为也用作页面标题的 <h1> 标记,并添加 [ X181X] 标签包含有关应用程序的一些信息。

保存并关闭文件。

在开发服务器运行的情况下,使用浏览器访问以下 URL:

http://127.0.0.1:5000/about

您将看到类似于以下内容的页面:

请注意导航栏和部分标题是如何从基本模板继承的。

您现在已经创建了一个基本模板并在您的索引页面和关于页面中使用它以避免代码重复。 导航栏中的链接此时不执行任何操作。 在下一步中,您将学习如何通过修复导航栏链接来链接模板中的路线。

第 3 步 - 页面之间的链接

在此步骤中,您将学习如何使用 url_for() 辅助函数在模板中的页面之间进行链接。 您将向基本模板中的导航栏添加两个链接,一个用于索引页面,一个用于“关于”页面。

首先打开您的基本模板进行编辑:

nano templates/base.html

编辑该文件,如下所示:

flask_app/templates/base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %} {% endblock %} - FlaskApp</title>
    <style>
        nav a {
            color: #d64161;
            font-size: 3em;
            margin-left: 50px;
            text-decoration: none;
        }
    </style>
</head>
<body>
    <nav>
        <a href="{{ url_for('hello') }}">FlaskApp</a>
        <a href="{{ url_for('about') }}">About</a>
    </nav>
    <hr>
    <div class="content">
        {% block content %} {% endblock %}
    </div>
</body>
</html>

在这里,您使用特殊的 url_for() 函数,该函数将返回您给它的视图函数的 URL。 第一个链接链接到 hello() 视图函数的路由(即索引页)。 第二个链接链接到about()视图函数的路径。 请注意,您传递的是视图函数的名称,而不是路由(//about)。

使用 url_for() 功能构建 URL 可以帮助您更好地管理 URL。 如果您对 URL 进行硬编码,则在您编辑路由时您的链接将会中断。 使用 url_for(),您可以编辑路线并保证链接仍将按预期工作。 url_for() 函数还负责转义特殊字符等其他事情。

保存并关闭文件。

现在转到索引页面并尝试导航栏中的链接。 您会看到它们按预期工作。

您学习了如何使用 url_for() 函数链接到模板中的其他路由。 接下来,您将添加一些条件语句来根据您设置的条件控制模板中显示的内容,并在模板中使用 for 循环来显示列表项。

第 4 步 - 使用条件和循环

在此步骤中,您将在模板中使用 if 语句来控制根据特定条件显示的内容。 您还将使用 for 循环遍历 Python 列表并显示列表中的每个项目。 您将添加一个在列表中显示评论的新页面。 索引号为偶数的评论将以蓝色背景显示,而索引号为奇数的评论将以灰色背景显示。

首先,您将为评论页面创建一个路由。 打开 app.py 文件进行编辑:

nano app.py

在文件末尾添加以下路由:

烧瓶应用程序/app.py

# ...

@app.route('/comments/')
def comments():
    comments = ['This is the first comment.',
                'This is the second comment.',
                'This is the third comment.',
                'This is the fourth comment.'
                ]

    return render_template('comments.html', comments=comments)

在上面的路线中,您有一个名为 comments 的 Python 列表,其中包含四个项目。 (这些注释通常来自真实场景中的数据库,而不是像您在此处所做的那样进行硬编码。)您在最后一行返回一个名为 comments.html 的模板文件,并传递一个名为comments 包含模板文件的列表。

保存并关闭文件。

接下来,在templates目录下打开一个新的comments.html文件进行编辑:

nano templates/comments.html

将以下代码添加到文件中:

flask_app/templates/comments.html

{% extends 'base.html' %}

{% block content %}
    <h1>{% block title %} Comments {% endblock %}</h1>
    <div style="width: 50%; margin: auto">
        {% for comment in comments %}
        <div style="padding: 10px; background-color: #EEE; margin: 20px">
            <p style="font-size: 24px">{{ comment }}</p>
        </div>
        {% endfor %}
    </div>
{% endblock %}

在这里,您扩展 base.html 模板并替换 content 块的内容。 首先,您使用 <h1> 标题,它也用作页面的标题。

您在 {% for comment in comments %} 行中使用 Jinja for 循环来遍历 comments 列表中的每个注释(存储在 comment 变量中)。 您在 <p style="font-size: 24px">模板:Comment</p> 标签中显示注释的方式与通常在 Jinja 中显示变量的方式相同。 您使用 {% endfor %} 关键字表示 for 循环的结束。 这与 Python for 循环的构造方式不同,因为 Jinja 模板中没有特殊的缩进。

保存并关闭文件。

在开发服务器运行的情况下,打开浏览器并访问评论页面:

http://127.0.0.1:5000/comments

您将看到类似于以下内容的页面:

现在,您将在模板中使用 if 条件语句,通过显示带有灰色背景的奇数索引号的注释和带有蓝色背景的偶数索引号的注释。

打开 comments.html 模板文件进行编辑:

nano templates/comments.html

将其编辑为如下所示:

flask_app/templates/comments.html

{% extends 'base.html' %}

{% block content %}
    <h1>{% block title %} Comments {% endblock %}</h1>
    <div style="width: 50%; margin: auto">
        {% for comment in comments %}
            {% if loop.index % 2 == 0 %}
                {% set bg_color = '#e6f9ff' %}
            {% else %}
                {% set bg_color = '#eee' %}
            {% endif %}

            <div style="padding: 10px; background-color: {{ bg_color }}; margin: 20px">
                <p>#{{ loop.index }}</p>
                <p style="font-size: 24px">{{ comment }}</p>
            </div>
        {% endfor %}
    </div>
{% endblock %}

通过这个新编辑,您在 {% if loop.index % 2 == 0 %} 行中添加了 if 语句。 循环变量 是一个特殊的 Jinja 变量,可让您访问有关当前循环的信息。 在这里,您使用 loop.index 获取当前项目的索引,该索引从 1 开始,而不是 Python 列表中的 0

此处的 if 语句检查索引是否甚至使用 % 运算符。 它检查索引号除以 2 的余数; 如果余数为 0 则索引号为偶数,否则索引号为奇数。 您使用 {% set %} 标签来声明一个名为 bg_color 的变量。 如果索引号为偶数,则将其设置为蓝色,否则,如果索引号为奇数,则将 bg_color 变量设置为灰色。 然后使用 bg_color 变量为包含注释的 <div> 标记设置背景颜色。 在注释文本上方,您使用 loop.index<p> 标记中显示当前索引号。

保存并关闭文件。

打开浏览器并访问评论页面:

http://127.0.0.1:5000/comments

您将看到新的评论页面:

这是如何使用 if 语句的演示。 但是您也可以通过使用特殊的 loop.cycle() Jinja 助手来实现相同的效果。 为了演示这一点,打开 comments.html 文件:

nano templates/comments.html

将其编辑为如下所示:

flask_app/templates/comments.html

{% extends 'base.html' %}

{% block content %}
    <h1>{% block title %} Comments {% endblock %}</h1>
    <div style="width: 50%; margin: auto">
        {% for comment in comments %}
            <div style="padding: 10px;
                        background-color: {{ loop.cycle('#EEE', '#e6f9ff') }};
                        margin: 20px">
                <p>#{{ loop.index }}</p>
                <p style="font-size: 24px">{{ comment }}</p>
            </div>
        {% endfor %}
    </div>
{% endblock %}

在这里,您删除了 if/else 语句并使用 loop.cycle('#EEE', '#e6f9ff') 帮助器在两种颜色之间循环。 background-color 的值将是 #EEE 一次和 #e6f9ff 另一个。

保存并关闭文件。

在浏览器中打开评论页面,刷新一下,你会发现这和if语句的效果是一样的。

您可以将 if 语句用于多种用途,包括控制页面上显示的内容。 例如,要显示除第二条之外的所有评论,您可以使用带有条件 loop.index != 2if 语句来过滤掉第二条评论。

打开评论模板:

nano templates/comments.html

并将其编辑为如下所示:

flask_app/templates/comments.html

{% extends 'base.html' %}

{% block content %}
    <h1>{% block title %} Comments {% endblock %}</h1>
    <div style="width: 50%; margin: auto">
        {% for comment in comments %}
            {% if loop.index != 2 %}
                <div style="padding: 10px;
                            background-color: #EEE;
                            margin: 20px">
                    <p>#{{ loop.index }}</p>
                    <p style="font-size: 24px">{{ comment }}</p>
                </div>
            {% endif %}
        {% endfor %}
    </div>
{% endblock %}

在这里,您使用 {% if loop.index != 2 %} 仅显示没有索引 2 的评论,这意味着除了第二条之外的所有评论。 您还为背景颜色使用硬编码值而不是 loop.cycle() 帮助器以使事情变得更简单,其余部分保持不变。 使用 {% endif %} 结束 if 语句。

保存并关闭文件。

刷新评论页面,你会看到第二条评论没有显示出来。

您现在需要添加一个链接,将用户带到导航栏中的“评论”页面。 打开基本模板进行编辑:

nano templates/base.html

通过添加一个新的 <a> 链接来编辑 <nav> 标签的内容:

flask_app/templates/base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %} {% endblock %} - FlaskApp</title>
    <style>
        nav a {
            color: #d64161;
            font-size: 3em;
            margin-left: 50px;
            text-decoration: none;
        }
    </style>
</head>
<body>
    <nav>
        <a href="{{ url_for('hello') }}">FlaskApp</a>
        <a href="{{ url_for('comments') }}">Comments</a>
        <a href="{{ url_for('about') }}">About</a>
    </nav>
    <hr>
    <div class="content">
        {% block content %} {% endblock %}
    </div>
</body>
</html>

在这里,您使用 url_for() 帮助器链接到 comments() 视图函数。

保存并关闭文件。

导航栏现在将有一个链接到评论页面的新链接。

您在模板中使用 if 语句来控制根据特定条件显示的内容。 您使用 for 循环遍历 Python 列表并显示列表中的每个项目,并了解了 Jinja 中特殊的 loop 变量。 接下来,您将使用 Jinja 过滤器来控制可变数据的显示方式。

第 5 步 — 使用过滤器

在此步骤中,您将学习如何在模板中使用 Jinja 过滤器。 您将使用 upper 过滤器将您在上一步中添加的注释转换为大写,您将使用 join 过滤器将一系列字符串连接成一个字符串,您将了解如何使用 safe 过滤器呈现受信任的 HTML 代码而不转义它。

首先,您将评论页面中的评论转换为大写。 打开comments.html模板进行编辑:

nano templates/comments.html

将其编辑为如下所示:

flask_app/templates/comments.html

{% extends 'base.html' %}

{% block content %}
    <h1>{% block title %} Comments {% endblock %}</h1>
    <div style="width: 50%; margin: auto">
        {% for comment in comments %}
            {% if loop.index != 2 %}
                <div style="padding: 10px;
                            background-color: #EEE;
                            margin: 20px">
                    <p>#{{ loop.index }}</p>
                    <p style="font-size: 24px">{{ comment | upper }}</p>
                </div>
            {% endif %}
        {% endfor %}
    </div>
{% endblock %}

在这里,您使用管道符号 (|) 添加了 upper filter。 这会将 comment 变量的值修改为大写。

保存并关闭文件。

在开发服务器运行的情况下,使用浏览器打开评论页面:

http://127.0.0.1:5000/comments

应用过滤器后,您可以看到评论全部为大写。

过滤器也可以在括号中接受参数。 为了演示这一点,您将使用 join 过滤器来加入 comments 列表中的所有评论。

打开评论模板:

nano templates/comments.html

将其编辑为如下所示:

flask_app/templates/comments.html

{% extends 'base.html' %}

{% block content %}
    <h1>{% block title %} Comments {% endblock %}</h1>
    <div style="width: 50%; margin: auto">
        {% for comment in comments %}
            {% if loop.index != 2 %}
                <div style="padding: 10px;
                            background-color: #EEE;
                            margin: 20px">
                    <p>#{{ loop.index }}</p>
                    <p style="font-size: 24px">{{ comment | upper }}</p>
                </div>
            {% endif %}
        {% endfor %}
        <hr>
        <div>
            <p>{{ comments | join(" | ") }}</p>
        </div>
    </div>
{% endblock %}

在这里,您添加了一个 <hr> 标记和一个 <div> 标记,您可以使用 join() 过滤器加入 comments 列表中的所有评论。

保存并关闭文件。

刷新评论页面,你会看到类似下面的页面:

如您所见,显示的 comments 列表带有由管道符号分隔的注释,这是您传递给 join() 过滤器的内容。

另一个重要的过滤器是 safe 过滤器,它允许您在浏览器上呈现受信任的 HTML。 为了说明这一点,您将使用 {{ }} Jinja 分隔符将一些包含 HTML 标记的文本添加到您的评论模板中。 在现实世界的场景中,这将作为来自服务器的变量。 然后将 join() 参数编辑为 <hr> 标记而不是管道符号。

打开评论模板:

nano templates/comments.html

将其编辑为如下所示:

flask_app/templates/comments.html

{% extends 'base.html' %}

{% block content %}
    <h1>{% block title %} Comments {% endblock %}</h1>
    <div style="width: 50%; margin: auto">
        {% for comment in comments %}
            {% if loop.index != 2 %}
                <div style="padding: 10px;
                            background-color: #EEE;
                            margin: 20px">
                    <p>#{{ loop.index }}</p>
                    <p style="font-size: 24px">{{ comment | upper }}</p>
                </div>
            {% endif %}
        {% endfor %}
        <hr>
        <div>
            {{ "<h1>COMMENTS</h1>" }}
            <p>{{ comments | join(" <hr> ") }}</p>
        </div>
    </div>
{% endblock %}

在这里,您添加了值 "<h1>COMMENTS</h1>" 并将连接参数更改为 <hr> 标记。

保存并关闭文件。

刷新评论页面,你会看到类似下面的页面:

如您所见,没有呈现 HTML 标签。 这是 Jinja 中的一项安全功能,因为某些 HTML 标签可能是有害的,并可能导致 跨站点脚本 (XSS) 攻击。 您应该只允许在浏览器中呈现受信任的 HTML。

要呈现上面的 HTML 标记,请打开评论模板文件:

nano templates/comments.html

通过添加 safe 过滤器对其进行编辑:

flask_app/templates/comments.html

{% extends 'base.html' %}

{% block content %}
    <h1>{% block title %} Comments {% endblock %}</h1>
    <div style="width: 50%; margin: auto">
        {% for comment in comments %}
            {% if loop.index != 2 %}
                <div style="padding: 10px;
                            background-color: #EEE;
                            margin: 20px">
                    <p>#{{ loop.index }}</p>
                    <p style="font-size: 24px">{{ comment | upper }}</p>
                </div>
            {% endif %}
        {% endfor %}
        <hr>
        <div>
            {{ "<h1>COMMENTS</h1>" | safe }}
            <p>{{ comments | join(" <hr> ") | safe }}</p>
        </div>
    </div>
{% endblock %}

您可以看到,您还可以像在 <p>模板:Comments</p> 行中那样链接过滤器。 每个过滤器都应用于前一个过滤器的结果。

保存并关闭文件。

刷新评论页面,您会看到 HTML 标签现在按预期呈现:

警告: 对来自未知数据源的 HTML 使用 safe 过滤器可能会使您的应用程序遭受 XSS 攻击。 除非您正在呈现的 HTML 来自受信任的来源,否则请勿使用它。


有关更多信息,请查看内置 Jinja 过滤器 列表。

您现在已经学习了如何在 Jinja 模板中使用过滤器来修改变量值。 接下来,您将集成 Bootstrap 工具包 来为您的应用程序设置样式。

第 6 步 — 集成 Bootstrap

在这一步中,您将学习如何使用 Bootstrap 工具包 来设置应用程序的样式。 您将在基本模板中添加一个 Bootstrap 导航栏,该导航栏将出现在从基本模板继承的所有页面中。

Bootstrap 工具包可帮助您设置应用程序的样式,使其更具视觉吸引力。 它还将帮助您将响应式网页合并到您的 Web 应用程序中,使其在移动浏览器上运行良好,而无需编写您自己的 HTML、CSS 和 JavaScript 代码来实现这些目标。

要使用 Bootstrap,您需要将其添加到基本模板中,以便可以在所有其他模板中使用它。

打开 base.html 模板,进行编辑:

nano templates/base.html

将其编辑为如下所示:

flask_app/templates/base.html

<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <!-- Bootstrap CSS -->
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KyZXEAg3QhqLMpG8r+8fhAXLRk2vvoC2f3B09zVXn8CA5QIVfZOJ3BCsw2P0p/We" crossorigin="anonymous">

    <title>{% block title %} {% endblock %} - FlaskApp</title>
  </head>
  <body>
    <nav class="navbar navbar-expand-lg navbar-light bg-light">
    <div class="container-fluid">
        <a class="navbar-brand" href="{{ url_for('hello') }}">FlaskApp</a>
        <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
        </button>
        <div class="collapse navbar-collapse" id="navbarNav">
        <ul class="navbar-nav">
            <li class="nav-item">
              <a class="nav-link" href="{{ url_for('comments') }}">Comments</a>
            </li>
            <li class="nav-item">
              <a class="nav-link" href="{{ url_for('about') }}">About</a>
            </li>
        </ul>
        </div>
    </div>
    </nav>
    <div class="container">
        {% block content %} {% endblock %}
    </div>

    <!-- Optional JavaScript -->

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-U1DAWAznBHeqEIlVSCgzq+c9gqGAJn5c/t99JyeKa9xxaYpSvHU5awsuZVVFIhvj" crossorigin="anonymous"></script>

  </body>
</html>

上面的大部分代码都是使用它所需的 Bootstrap 样板。 您有一些元标记,在 <head> 部分中有一个指向 Bootstrap CSS 文件的链接,在底部有一个指向可选 JavaScript 的链接。 代码中突出显示的部分包含前面步骤中解释的 Jinja 代码。 注意你如何使用特定的标签和 CSS 类来告诉 Bootstrap 如何显示每个元素。

在上面的 <nav> 标记中,您有一个 <a> 标记,其类别为 navbar-brand,它决定了导航栏中的品牌链接。 在 <ul class="navbar-nav"> 标记内,您在 <li> 标记中的 <a> 标记内有常规导航栏项目。

要了解有关这些标签和 CSS 类的更多信息,请参阅 Bootstrap 组件

保存并关闭文件。

在开发服务器运行的情况下,使用浏览器打开索引页面:

http://127.0.0.1:5000/

您将看到类似于以下内容的页面:

您现在可以使用 Bootstrap 组件在您的 Flask 应用程序中的所有模板中设置项目的样式。

结论

您现在知道如何在 Flask Web 应用程序中使用 HTML 模板。 您使用变量将数据从服务器传递到模板,使用模板继承来避免重复,合并元素,例如 if 条件和 for 循环,并在不同页面之间链接。 您了解了用于修改文本和显示可信 HTML 的过滤器,并将 Bootstrap 集成到您的应用程序中。

如果您想了解更多关于 Flask 的信息,请查看 Flask 主题页面