(二)Flask初体验——模板
(二)Flask初体验——模板
AllenOR灵感 发表于5个月前
(二)Flask初体验——模板
  • 发表于 5个月前
  • 阅读 3
  • 收藏 0
  • 点赞 0
  • 评论 0

新睿云服务器60天免费使用,快来体验!>>>   


Flask 学习目录

(一)Flask初体验——Hello World
(二)Flask初体验——模板
(三)Flask初体验——web 表单


如果你已经学习了前面的 Hello World 章节,那么你应该已经有了一个完全工作的简单的 web 应用程序,它的文件结构如下:

microblog/
├── app
│   ├── __init__.py
│   ├── __init__.pyc
│   ├── static
│   ├── templates
│   ├── views.py
│   └── views.pyc
├── run.py
└── tmp

在 Python 中生成 HTML 代码并不简单,而且非常麻烦,因为你必须自行做好 HTML 转义以保持应用程序的安全。由于这个原因,Flask 自动为你配置好 Jinja2 模板。所以在这里我们介绍一下模板的基本概念以及基本用法。

为什么我们需要模板

让我们来考虑一下我们该如何扩充这个小的应用程序。

我们希望我们的微博应用程序的主页上有一个欢迎登录用户的标题,而且这是这种类型的应用程序的一个“标配”。

输出一个漂亮的大标题的一个容易的选择就是改变我们的视图功能,输出 HTML ,也许像这个样子:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from app import app

@app.route('/')
@app.route('/index')

def index():
    user = { 'nickname': 'Miguel' } # fake user
    return '''
            <html>
              <head>
                <title>Home Page</title>
              </head>
              <body>
                <h1>Hello, ''' + user['nickname'] + '''</h1>
              </body>
            </html>
            '''

接着你运行看看浏览器上的显示情况,如下图:


因为我们暂时还不支持用户,所以暂时使用了占位符的用户对象,有时也被成为假冒或模仿的对象。这样让我们可以集中关注应用程序的磨一方面,而不用花心思在暂未完成的部分上面。

但是,上面的解决方案是非常难看的,而且如果你需要构建一个大型的网站,那么其中就会设计到大量的复杂的 HTML 页面,这样就会使代码非常复杂。所以,Flask 为我们准备了 Jinja2 模板。接下来,我们学习一下 Jinja2 模板。

模板从天而降

如果你能够保持你的应用程序与网页的布局或者界面逻辑上是分开的,这样不是显得更加容易组织?难道你不觉得是这样吗?而模板可以帮助实现这种分离。

让我们编写第一个我们的模板,文件位置是 app/templates/index.html

<html>
  <head>
    <title>{{title}} - microblog</title>
  </head>
  <body>
      <h1>Hello, {{user.nickname}}!</h1>
  </body>
</html>

正如你在上面看到的,我们只是写了一个大部分标准的 HTML 页面,唯一的区别是有一些动态内容的在 {{...}} 中。

现在看看怎样在我们的视图函数中使用这些模板,文件位置是 app/views.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from app import app
from flask import render_template

@app.route('/')
@app.route('/index')

def index():
    user = { 'nickname': 'Miguel' } # fake user
    return render_template("index.html",
            title = 'Home',
            user = user)

试着运行下应用程序看看模板是如何工作的。一旦在你的浏览器上呈现该网页,你可以浏览下 HTML 源代码,与原始的模板内容对比下差别。

为了渲染模板,我们必须从 Flask 框架中导入一个名为 render_template 的新函数。此函数需要传入模板名以及一些模板变量列表,返回一个所有变量被替换的渲染的模板。

在内部,render_template 调用了 Jinja2 模板引擎,Jinja2 模板引擎是 Flask 框架的一部分。Jinja2 会把模板参数提供的相应的值替换了 {{...}} 块。

模板中控制语句

Jinja2 模板同样支持控制语句,像在 {{...}} 块中。让我们在我们的模板中添加一个 if 声明,文件位置是 app/templates/index.html

<html>
  <head>
      {% if title %}
    <title>{{title}} - microblog</title>
    {% else %}
    <title>Welcome to microblog</title>
    {% endif %}
  </head>
  <body>
      <h1>Hello, {{user.nickname}}!</h1>
  </body>
</html>

现在我们的模板变得更加智能了。如果视图函数忘记输入页面标题的参数,也不会出发异常反而会出现我们自己提供的标题。放心地去掉视图函数中 render_template 的调用中的 title 参数,看看 if 语句是如何工作的!

模板中的循环语句

在我们 microblog 应用程序中,登录的用户想要在首页展示他的或者她的联系人列表中用户最近的文章,因此让我们看看如何才能做到。

首先我们先创建一些用户以及他们的文章用来展示,文件位置是 app/views.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from app import app
from flask import render_template

@app.route('/')
@app.route('/index')

def index():
    user = { 'nickname': 'Miguel' } # fake user
    # 其实这里可以从数据库中读取,然后在前端显示
    posts = [
        {
            'author': {'nickname': 'John'},
            'body': 'Beautiful day in Portland!'
        },
        {
            'author': {'nickname': 'Susan'},
            'body': 'The Avengers movie was so cool!'
        }
    ]
    return render_template("index.html",
            title = 'Home',
            user = user,
            posts = posts)

在使用模板这一方面,我们必须解决一个新问题。列表中可能有许多元素,多少篇文章被展示将取决于视图函数。模板不会假设有多少文章,因此它必须准备渲染视图传送的文章数量。

因此让我们来看看怎么使用 for 来做到这一点,文件位置是 app/templates/index.html

<html>
  <head>
      {% if title %}
    <title>{{title}} - microblog</title>
    {% else %}
    <title>Welcome to microblog</title>
    {% endif %}
  </head>
  <body>
      <h1>Hello, {{user.nickname}}!</h1>
      {% for post in posts %}
      <p>{{post.author.nickname}} says: <b>{{post.body}}</b></p>
      {% endfor %}
  </body>
</html>

接着你可以在浏览器中试试,可以看到以下页面:


模板继承

在我们的 microblog 应用程序中,在页面的顶部需要一个导航栏。在导航栏里面有编辑账号,登出等等的链接。

我们可以在 index.html 模板中添加一个导航栏,但是随着应用的扩展,越来越多的模板需要这个导航栏,我们需要在每一个模板中复制这个导航栏。然而你必须要保证每一个导航栏都要同步,如果你有大量的模板,这需要花费很大的力气。

相反,我们可以利用 Jinja2 的模板集成的特点,这允许我们把所有模板公共的部分移除出页面的布局,接着把我们放在一个基础模板中,所有使用它的模板可以导入这个基础模板。

所有让我们定义一个基础模板,爱模板包含导航栏以及上面谈论的标题,文件位置是 app/templates/base.html

<html>
  <head>
      {% if title %}
    <title>{{title}} - microblog</title>
    {% else %}
    <title>Welcome to microblog</title>
    {% endif %}
  </head>
  <body>
      <div>Microblog: <a href="/index">Home</a></div>
      <hr>
      {% block content %}
      {% endblock %}
  </body>
</html>

在这个模板中,我们使用 block 控制语句来定义派生模板可以出入的地方,块被赋予唯一的名字。

接下来,我们需要修改我们的 index.html 模板,来继承来自 base.html 文件,index.html 文件位置是 app/templates/index.html

{% extends "base.html" %}
{% block content %}
    <h1>Hello, {{user.nickname}}!</h1>
    {% for post in posts %}
    <p>{{post.author.nickname}} says: <b>{{post.body}}</b></p>
    {% endfor %}
{% endblock %}

接下来,你可以尝试运行一下这个程序,你可以看到以下页面:


至此,我们学会了如何使用 Jinja2 模板来编写前端网页。


参考资料:

Flask 模板

Flask 文档

  • 打赏
  • 点赞
  • 收藏
  • 分享
共有 人打赏支持
粉丝 6
博文 2139
码字总数 82983
×
AllenOR灵感
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
* 金额(元)
¥1 ¥5 ¥10 ¥20 其他金额
打赏人
留言
* 支付类型
微信扫码支付
打赏金额:
已支付成功
打赏金额: