在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应用程序:

from flask import Flask

app = Flask(__name__)

@app.route('/')
@app.route('/hello')
@app.route('/hello/<user>')
def hello_world(user=None):
    user = user or 'Shalabh'
    return '''
    <html>
        <head>
            <title>Templating in Flask</title>
        </head>
        <body>
            <h1>Hello %s!</h1>
            <p>Welcome to the world of Flask!</p>
        </body>
    </html>''' % user
       
if __name__ == '__main__':
    app.run()

显然,在HTML,CSS和JS代码成千上万行的真实Web应用程序中,上述编写应用程序的模式是不可行的。 在这里,模板可以节省我们的时间,因为我们可以通过使模板分开来构造视图代码。 Flask默认情况下提供对Jinja2的支持,但也可以使用任何其他模板引擎。

布置模板

默认情况下,Flask希望将模板放置在应用程序根级别的名为templates的文件夹中。 然后Flask通过使该文件夹可用于render_template()方法来自动读取内容。 我将通过重组上面显示的琐碎的Hello World应用程序来演示相同的内容。

应用程序结构如下所示。

flask_app/
    my_app.py    
    templates/
        - index.html

应用本身

flask_app / my_app.py

from flask import Flask, render_template, request

app = Flask(__name__)

@app.route('/')
@app.route('/hello')
@app.route('/hello/<user>')
def hello_world(user=None):
    user = user or 'Shalabh'
    return render_template('index.html', user=user)

flask_app / templates / index.html

<html>
  <head>
    <title>Templating in Flask</title>
  </head>
  <body>
    <h1>Hello {{ user }}!</h1>
    <p>Welcome to the world of Flask!</p>
  </body>
</html>

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

flask --app=my_app run

在浏览器中打开http://127.0.0.1:5000/以查看实际应用程序。 如果使用http://127.0.0.1:5000/hello ,结果也将相同。

默认登录页面

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

使用自定义名称访问登录页面

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

了解模板中的块和继承

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

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

flask_app/
    my_app.py    
    templates/
        - base.html
        - home.html
        - product.html
    static/
        css/
            - bootstrap.min.css
            - main.css
        js/
            - bootstrap.min.js

在这里,可以从上述引导网站下载static/css/bootstrap.min.cssstatic/js/bootstrap.min.js 。 其余的应用程序代码如下所示。

flask_app / my_app.py

from flask import Flask, render_template, abort

app = Flask(__name__)

PRODUCTS = {
    'iphone': {
        'name': 'iPhone 5S',
        'category': 'Phones',
        'price': 699,
    },
    'galaxy': {
        'name': 'Samsung Galaxy 5',
        'category': 'Phones',
        'price': 649,
    },
    'ipad-air': {
        'name': 'iPad Air',
        'category': 'Tablets',
        'price': 649,
    },
    'ipad-mini': {
        'name': 'iPad Mini',
        'category': 'Tablets',
        'price': 549
    }
}

@app.route('/')
@app.route('/home')
def home():
    return render_template('home.html', products=PRODUCTS)

@app.route('/product/<key>')
def product(key):
    product = PRODUCTS.get(key)
    if not product:
        abort(404)
    return render_template('product.html', product=product)

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

flask_app / static / css / main.css

body {
  padding-top: 50px;
}
.top-pad {
  padding: 40px 15px;
  text-align: center;
}

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

flask_app / templates / base.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Jinja2 Tutorial - Tutsplus</title>
    <link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" rel="stylesheet">
    <link href="{{ url_for('static', filename='css/main.css') }}" rel="stylesheet">
  </head>
  <body>
    <div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
      <div class="container">
        <div class="navbar-header">
          <a class="navbar-brand" href="{{ url_for('home')}}">Tutsplus - Jinja2 Tutorial</a>
        </div>
      </div>
    </div>
    <div class="container">
      {% block container %}{% endblock %}
    </div>
    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
    <script src="{{ url_for('static', filename='js/bootstrap.min.js') }}"></script>
  </body>
</html>

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

flask_app / templates / home.html

{% extends 'base.html' %}

{% block container %}
  <div class="top-pad">
    {% for id, product in products.iteritems() %}
      <div class="well">
        <h2>
          <a href="{{ url_for('product', key=id) }}">{{product['name'] }}</a>
          <small>$ {{ product['price'] }}</small>
        </h2>
      </div>
    {% endfor %}
  </div>
{% endblock %}

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

flask_app / templates / product.html

{% extends 'home.html' %}

{% block container %}
  <div class="top-pad">
    <h1>{{ product['name'] }}
      <small>{{ product['category'] }}</small>
    </h1>
    <h3>$ {{ product['price'] }}</h3>
  </div>
{% endblock %}

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

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

flask --app=my_app run

正在运行的应用看起来像下面的屏幕截图所示。 只需在浏览器中打开http://127.0.0.1:5000/home

使用Bootstrap框架运行的应用程序

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

单个产品页面

结论

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

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

翻译自: https://code.tutsplus.com/tutorials/templating-with-jinja2-in-flask-essentials--cms-25571

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值