• 日常搜索
  • 百度一下
  • Google
  • 在线工具
  • 搜转载

在 Flask 中使用 Jinja2 进行模板制作:基础知识

jinja2是一个用纯 python 编写的模板引擎。它提供受Django启发的非 XML 语法,但支持内联表达式和可选的沙盒环境。除了是一个易于使用的独立模板引擎之外,它体积小但速度快。flask是一个基于 Python 的微型 Web 框架,可让您快速高效地编写 Web 应用程序

在这个由三部分组成的系列中,我将从 Flask 的角度介绍 Jinja2 模板的基础知识。在本系列的后续部分中,我将介绍高级模板主题,同时学习如何以模块化和可扩展的设计在基于 Flask 的应用程序中布置模板。

我假设您对 Flask 和环境设置最佳实践有基本的了解,在开发 Python 应用程序时应遵循使用virtualenv的最佳实践。

安装包

Flask 与 Jinja2 打包在一起,因此我们只需要安装 Flask。对于本系列,我建议使用 Flask 的开发版本,它包括更稳定的命令行支持以及许多其他功能和对 Flask 的总体改进。

pip install https://github.com/mitsuhiko/flask/tarball/master

需要模板引擎吗?

在 Flask 中,我们可以编写一个完整的 Web 应用程序,而不需要任何第三方模板引擎。让我们看看Hello World下面的一个小应用程序:

1    from flask import Flask    
2    
3    app = Flask(__name__)    
4    
5    @app.route('/')    
6    @app.route('/hello')    
7    @app.route('/hello/<user>')    
8    def hello_world(user=None):    
9        user = user or 'Shalabh'    
10        return '''     
11    <html>     
12    <head>     
13    <title>Templating in Flask</title>     
14    </head>     
15    <body>     
16    <h1>Hello %s!</h1>     
17    <p>Welcome to the world of Flask!</p>     
18    </body>     
19    </html>''' % user    
20    
21    if __name__ == '__main__':    
22        app.run()

很明显,上述编写应用程序的模式对于真正的 HTML、css 和 JS 代码在数千行代码范围内的 Web 应用程序是不可行的。在这里,模板化拯救了我们,因为我们可以通过保持我们的模板分离来构造我们的视图代码。Flask 默认支持 Jinja2,但也可以根据需要使用任何其他模板引擎。

布局模板

默认情况下,Flask 期望将模板放置在以templates应用程序根级别命名的文件夹中。Flask 然后通过使该文件夹可供该render_template()方法使用来自动读取内容。我将通过重构Hello World上面显示的简单应用程序来证明这一点。

应用程序结构如下所示。

1    flask_app/    
2        my_app.py        
3        templates/    
4            - index.html

应用程序本身

flask_app/my_app.py

1    from flask import Flask, render_template, request    
2    
3    app = Flask(__name__)    
4    
5    @app.route('/')    
6    @app.route('/hello')    
7    @app.route('/hello/<user>')    
8    def hello_world(user=None):    
9        user = user or 'Shalabh'    
10        return render_template('index.html', user=user)

flask_app/templates/index.html

1    <html>    
2      <head>    
3        <title>Templating in Flask</title>    
4      </head>    
5      <body>    
6        <h1>Hello {{ user }}!</h1>    
7        <p>Welcome to the world of Flask!</p>    
8      </body>    
9    </html>

要运行该应用程序,只需在命令行中执行以下命令:

flask --app=my_app run 

在浏览器中打开http://127.0.0.1:5000/以查看正在运行的应用程序。在http://127.0.0.1:5000/hello的情况下,结果也是一样的。

在 Flask 中使用 Jinja2 进行模板制作:基础知识  第1张

尝试打开以您的名字作为最后一部分的 URL。因此,如果您的名字是 John,则 URL 将为http://127.0.0.1:5000/hello/John。现在页面看起来像这样:

在 Flask 中使用 Jinja2 进行模板制作:基础知识  第2张

非常简单的是,在该方法hello_world中,URL 的最后一部分hello是从请求中获取并传递到使用render_template(). 然后使用 Jinja2 占位符从模板上下文中解析该值{{ user }}。该占位符根据模板上下文评估放置在其中的所有表达式。

了解模板中的块和继承

通常,任何 Web 应用程序都会有许多彼此不同的网页。页眉和页脚等代码块在整个站点的几乎所有页面中都是相同的。同样,菜单也保持不变。事实上,通常只有中心容器块发生变化,其余的通常保持不变。为此,Jinja2 提供了一种很好的模板间继承方式。拥有一个基本模板是一个很好的做法,我们可以在其中构造站点的基本布局以及页眉和页脚。

我将创建一个小型应用程序来展示不同类别下的产品列表。对于样式,我将使用Bootstrap框架为模板提供基本设计。应用程序结构现在如下所示。

1    flask_app/    
2        my_app.py        
3        templates/    
4            - base.html    
5            - home.html    
6            - product.html    
7        static/    
8            css/    
9                - main.css

下面演示了其余的应用程序代码。

flask_app/my_app.py

1  from flask import Flask, render_template, abort    
2    
3    app = Flask(__name__)    
4    
5    PRODUCTS = {    
6        'iphone': {    
7            'name': 'iPhone 5S',    
8            'category': 'Phones',    
9            'price': 699,    
10        },    
11        'galaxy': {    
12            'name': 'Samsung Galaxy 5',    
13            'category': 'Phones',    
14            'price': 649,    
15        },    
16        'ipad-air': {    
17            'name': 'iPad Air',    
18            'category': 'Tablets',    
19            'price': 649,    
20        },    
21        'ipad-mini': {    
22            'name': 'iPad Mini',    
23            'category': 'Tablets',    
24            'price': 549    
25        }    
26    }    
27    
28    @app.route('/')    
29    @app.route('/home')    
30    def home():    
31        return render_template('home.html', products=PRODUCTS)    
32    
33    @app.route('/product/<key>')    
34    def product(key):    
35        product = PRODUCTS.get(key)    
36        if not product:    
37            abort(404)    
38        return render_template('product.html', product=product)

在这个文件中,我对产品列表进行了硬编码,以使应用程序更简单,并且只关注模板部分。我创建了两个端点,home和product,其中前者用于列出所有产品,后者用于打开单个页面。

flask_app/static/css/main.css

1   body {    
2      padding-top: 50px;    
3    }    
4    .top-pad {    
5      padding: 40px 15px;    
6      text-align: center;    
7    }

该文件包含一些我添加的自定义 CSS,以使模板更易读。现在让我们看一下模板。

flask_app/templates/base.html

1  <!DOCTYPE html>     
2    <html lang="en">     
3      <head>     
4        <meta charset="utf-8">     
5        <meta http-equiv="X-UA-Compatible" content="IE=edge">     
6        <meta name="viewport" content="width=device-width, initial-scale=1">     
7        <title>Jinja2 Tutorial - 老吴搭建教程</title>     
8        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">     
9        <link href="{{ url_for('static', filename='css/main.css') }}" rel="stylesheet">     
10      </head>     
11      <body>     
12        <div class="navbar navbar-inverse navbar-fixed-top" role="navigation">     
13          <div class="container">     
14            <div class="navbar-header">     
15              <a class="navbar-brand" href="{{ url_for('home')}}">老吴搭建教程 - Jinja2 Tutorial</a>     
16            </div>     
17          </div>     
18        </div>     
19        <div class="container">     
20          {% block container %}{% endblock %}     
21        </div>     
22        <!-- jquery (necessary for Bootstrap's javascript plugins) -->     
23    
24        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>     
25        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>     
26    
27      </body>     
28    </html>

请注意url_for()用于为静态文件和其他链接创建 URL 的用法。这是一个非常方便的工具,由 Flask 提供。在文档中阅读更多相关信息。这里要注意的另一个重点是 的使用{% block container %}{% endblock %},这是 Jinja2 致力于使模板模块化和可继承的非常重要的组成部分。接下来的几个文件将使这一点更清楚。

控制流

Python 使用if、elif、else和forloop 语句根据条件是真还是假来控制程序流。您还可以将这些条件合并到您的 Flask 应用程序中以循环遍历产品字典并将它们显示在主页上。这些条件语句放在{%  %}块内。更新home.html页面如下。

flask_app/templates/home.html

1   {% extends 'base.html' %}    
2    
3    {% block container %}    
4      <div class="top-pad">    
5        {% for id, product in products.items() %}    
6          <div class="well">    
7            <h2>    
8              <a href="{{ url_for('product', key=id) }}">{{product['name']}}</a>    
9              <small>$ {{ product['price']}}</small>    
10            </h2>    
11          </div>    
12        {% endfor %}    
13      </div>    
14    {% endblock %}

查看此模板如何扩展base.html和提供{% block container %}. {% for %}在我们这里用来创建产品列表的任何语言中,它的行为就像一个普通的 for 循环。

flask_app/templates/product.html

1    {% extends 'home.html' %}    
2    
3    {% block container %}    
4      <div class="top-pad">    
5        <h1>{{ product['name'] }}    
6          <small>{{ product['category'] }}</small>    
7        </h1>    
8        <h3>$ {{ product['price'] }}</h3>    
9      </div>    
10    {% endblock %}

上面的模板实现了单个产品页面。

现在通过执行以下命令运行应用程序。

flask --app=my_app run

正在运行的应用程序看起来像下面的屏幕截图中显示的那样。在浏览器中打开http://127.0.0.1:5000/home即可。

在 Flask 中使用 Jinja2 进行模板制作:基础知识  第3张

单击任何产品以查看单个产品页面。

在 Flask 中使用 Jinja2 进行模板制作:基础知识  第4张

过滤器

过滤器可以像使用 Python 方法一样应用于变量。Jinja 模板语言中的管道字符分隔过滤器。例如,假设您需要在主页上将产品名称大写;您将按upper如下方式应用过滤器。

1  {% extends 'base.html' %}    
2    
3    {% block container %}    
4      <div class="top-pad">    
5        {% for id, product in products.items() %}    
6          <div class="well">    
7            <h2>    
8              <a href="{{ url_for('product', key=id) }}">{{product['name']| upper }}</a>    
9              <small>$ {{ product['price']}}</small>    
10            </h2>    
11          </div>    
12        {% endfor %}    
13      </div>    
14    {% endblock %}

现在,如果您运行服务器,您应该注意到产品名称是全大写的。

在 Flask 中使用 Jinja2 进行模板制作:基础知识  第5张

结论

在本教程中,我们了解了如何使用 Jinja2 在基于 Flask 的应用程序中布置模板结构。我们还看到了如何使用块来利用模板中的继承。

在本系列的下一部分中,我们将了解如何编写自定义过滤器、自定义上下文处理器和宏。

文章目录
  • 安装包
  • 需要模板引擎吗?
  • 布局模板
  • 应用程序本身
    • flask_app/my_app.py
    • flask_app/templates/index.html
  • 了解模板中的块和继承
    • flask_app/my_app.py
    • flask_app/static/css/main.css
    • flask_app/templates/base.html
    • 控制流
    • flask_app/templates/home.html
    • flask_app/templates/product.html
  • 过滤器
  • 结论
  • 发表评论