在Python的Flask框架中使用模版的入门教程

 概述

如果你已经阅读过上一个章节,那么你应该已经完成了充分的准备工作并且创建了一个很简单的具有如下文件结构的Web应用:
 
microblog
    |-flask文件夹
    |-<一些虚拟环境的文件>
    |-app文件夹
    |  |-static文件夹
    |  |-templates文件夹
    |  |-__init__.py文件
    |  |-views.py文件
    |-tmp文件夹
    |-run.py文件

亲,想要运行这个程序么?那就运行这个run.py文件,然后在你的浏览器里边打开http://localhost:5000这个地址.

我们在后面的章节会不断地从前一章节结束的地方继续开发我们的应用,所以你要确保你的环境已经正确安装,并且你的应用能够正常运行.

为什么我们需要使用模板系统

让我们来考虑一下,我们接下来怎么样扩展我们的小程序.

我们要在微博应用里边实现一个非常基本的功能,在首页上面显示一个欢迎已登录用户的标题.暂且忽略当前应用里边没有用户的状况,我将会在稍后解决这个问题.

要显示一个美观大方的标题,最简单的方法就是改变我们提供视图的方式来显示一些HTML代码,不如这样子:\

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代码的小程序相当恶心。想想看,如果你用一些动态内容生成的一个复杂的HTML页面,并且想要在由这样的程序组成的网站中改变一些页面内容,这将会一件非常蛋疼的事情。

模板系统拯救世界

如果保持业务逻辑和表现的分离,你的网站结构将会组织的更好。不要不信,如果你用python完成了业务代码,你甚至可以请一个网站设计师帮你完成剩下的部分。模板系统就是帮你实现业务和表现分离的。

让我们完成第一个模板(fileapp/templates/index.html):

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

如你所见,我们只是写了一个普通的HTML页面,唯一跟HTML有区别的就是里面掺杂了一些以 {{ ... }} 组成的动态内容占位符。

现在让我们来看看视图函数中是如何处理这个模板的(fileapp/views.py):

from flask import render_template
from app import app

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

测试这段程序的重点就是看看模板系统是如何工作的。你可以比较浏览器中渲染后的html页面源码与模板文件源码之间的区别。

在上面的程序中,我们从 Flask 框架 import 了一个叫 render_template 的新函数,并用这个函数来渲染模板。并给这个函数赋予了模板文件名和一些变量作为参数。它将导入的变量替换掉模板中的变量占位符,并返回渲染后的模板。

让我们了解的更深入点。在 Flask 底层,render_template 函数实际上是调用了 Flask 的一个组件: Jinja2模板处理引擎。是 Jinjia2 用导入的变量替换掉了模板中对应的 {{ ... }} 代码块。

模板中的流程控制

Jinja2 模板系统还支持流程控制语句,我们来尝试一下在模板中添加一个 if 流程控制语句 (fileapp/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>

现在我们的模板文件有点智能了。如果我们在视图函数中忘了定义页面标题变量 title,它将会使用自已的标题替代。把视图函数中 render_template 里的 title 变量取消试试,看看这个 if 流程语句是如何工作的。

模板中使用循环

也许用户想在他的主页上展示好友最近写的文章,有点像人人,或者新浪微博那样的好友动态,接下来我们就要看看如何来完成这个功能。

首先,创建用户和文章 (fileapp/views.py):

def index():
  user = { 'nickname': 'Miguel' } # fake user
  posts = [ # fake array of 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)

用数组存储用户的文章,每一个数组元素都是一个字典,如上代码所示,这个dict的key是author和body,用来存储文章的作者和文章内容。当我们决定使用数据库来存储这些信息时,这个字典的key可以隐射为表的一个字段,这里为了给大家演示模板的使用,没有使用数据库相关的技术,简单地使用字典和数组模拟用户和他的好友最近发表的文章。

我们的模板文件现在有了一个新问题。我们刚刚创建了一个包含用户文章的内容数据,这个数组可能包含任意数量的文章。怎样才能让模板根据这个数组的数量自动渲染内容。

要解决这个问题,就需要一个新的流程控制语句:for循环。让我们来把 for循环添加到模板文件 (fileapp/templates/index.html)

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

很简单吧,你还可以在数组中添加更多的内容看看效果。
 
模板继承

接来下,我们需要给这个微博(microblog)添加一个导航菜单,里面包含 修改个人资料,退出登录 等类似的链接。

直接在 index.html 模板文件中直接加入这个导航条也是可行的,但是当我们有很多模板文件都包含这个导航条时,就会陷入为了修改导航条的某个地方而不得不在多个文件中往返编辑的尴尬境地。当包含这个导航条的文件越来越多时,你想死的心就会有了。

我们可以使用 Jinja2 的模板继承功能,它可以使我们把模板中一些公共的内容组合在一起创建一个基础模板,然后让其它模板继承这个基础模板。

我们先来定义一个基础模板,里面包含了导航条和那个最开始写的关于页面标题(title)的流程控制语句。(fileapp/templates/base.html):

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

在这个模板中,我们使用了 block 控制语句来定义继承模板内容的显示位置。注意:这个 block 语句中设置的名称必须唯一。

接下来让我们修改一下 index.html 模板,让它继承于刚刚添加的基础模板 base.html (fileapp/templates/index.html):

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

基础模板 base.html 帮我们搞定了页面结构和公共内容,所以这个 index.html 模板就成了这幅衰样了。extends 语句使两个模板关联了起来。Jinja2在渲染 index.html 模板时,发现 extends 语句,就会自动先引入 base.html 基础模板,并对两个模板中名为 content 的 block 语句进行匹配。Jinja2知道如何把两个模板合并到一起。我们以后创建新的模板时,同样也会使用这种从基础模板继承的方法。

结束语

如果你想节省时间,懒得敲代码,可以从以下地址下载本章内容的示例代码:

下载地址:microblog-0.2.zip

(0)

相关推荐

  • Python入门之modf()方法的使用

    modf()方法返回两个项的元组x的整数小数部分.这两个元组具有相同x符号.则返回一个浮点数的整数部分. 语法 以下是modf()方法的语法: import math math.modf( x ) 注意:此函数是无法直接访问的,所以我们需要导入math模块,然后需要用math的静态对象来调用这个函数. 参数 x -- 这是一个数值表达式 返回值 这种方法在两项的元组返回x的整数小数部分.具有相同的x符号.整数部分则返回一个浮点数. 例子 下面的例子显示了modf()方法的使用. #!/usr/b

  • 用Python进行行为驱动开发的入门教程

    为驱动开发(Behavior-Driven Development,BDD)是一种卓越的开发模式.能帮助开发者养成日清日结的好习惯,从而避免甚至杜绝"最后一分钟"的情况出现,因此对提高代码质量是大有裨益的.其与Gherkin语法相结合的测试结构及设计形式,使得对团队的全部成员包括非技术人员都具有极好的易读性. 所有代码都必须进行测试,这意味着上线时把系统瑕疵降到最低甚至为零.这需要与完整的测试套件相配,从整体把控软件行为,使得检测与维护都能有序进行.这就是BDD的魅力所在,难道不心动吗

  • Python简明入门教程

    本文实例讲述了Python简明入门教程.分享给大家供大家参考.具体如下: 一.基本概念 1.数 在Python中有4种类型的数--整数.长整数.浮点数和复数. (1)2是一个整数的例子. (2)长整数不过是大一些的整数. (2)3.23和52.3E-4是浮点数的例子.E标记表示10的幂.在这里,52.3E-4表示52.3 * 10-4. (4)(-5+4j)和(2.3-4.6j)是复数的例子. 2.字符串 (1)使用单引号(') (2)使用双引号(") (3)使用三引号('''或"&q

  • python绘图方法实例入门

    本文实例讲述了python绘图方法.分享给大家供大家参考.具体如下: # -*- coding:utf-8 -*- import matplotlib.pyplot as plt def main(): # 颜色列表 colorList = ['b','g','r','c','m','y','k'] # 共用的横坐标 threadList = [1,2,4,8,10] # 设置横坐标和纵坐标的名称 plt.xlabel('threads') plt.ylabel('concurrent') #

  • Python基础入门之seed()方法的使用

    seed() 设置生成随机数用的整数起始值.调用任何其他random模块函数之前调用这个函数. 语法 以下是seed()方法的语法: seed ( [x] ) 注意:此函数是无法直接访问的,所以需要导入seed模块,然后需要使用random静态对象来调用这个函数. 参数 x -- 这是下一个随机数的种子.如果省略,则需要系统时间,以产生下一个随机数. 返回值 此方法不返回任何值. 例子 下面的例子显示了seed()方法的使用. #!/usr/bin/python import random ra

  • Python入门教程之if语句的用法

    Python中的if语句是类似的其它语言的. if语句包含使用该数据进行比较,并根据比较的结果做出了决定的逻辑表达式. 语法: if语句在Python编程语言的语法是: if expression: statement(s) 如果布尔表达式的计算结果为true,那么if语句块将被执行.如果if语句布尔表达式计算为false,那么第一组代码将被执行. Python编程语言的假定任何非零和非null为true,如果是zero或null,则假定为false值. 例子: #!/usr/bin/pytho

  • 最基础的Python的socket编程入门教程

    本文介绍使用Python进行Socket网络编程,假设读者已经具备了基本的网络编程知识和Python的基本语法知识,本文中的代码如果没有说明则都是运行在Python 3.4下. Python的socket功能封装在socket库中,要使用socket,记得先import socket,socket库的详细介绍参见官方文档. 创建Socket 首先创建一个socket,使用socket库中得socket函数创建. import socket # create an INET, STREAM soc

  • Python编程入门的一些基本知识

    Python与Perl,C和Java语言等有许多相似之处.不过,也有语言之间有一些明确的区别.本章的目的是让你迅速学习Python的语法. 第一个Python程序: 交互模式编程: 调用解释器不经过脚本文件作为参数,显示以下提示: $ python Python 2.6.4 (#1, Nov 11 2014, 13:34:43) [GCC 4.1.2 20120704 (Red Hat 5.6.2-48)] on linux2 Type "help", "copyright&

  • 在Python的Flask框架中使用模版的入门教程

     概述 如果你已经阅读过上一个章节,那么你应该已经完成了充分的准备工作并且创建了一个很简单的具有如下文件结构的Web应用:   microblog     |-flask文件夹     |-<一些虚拟环境的文件>     |-app文件夹     |  |-static文件夹     |  |-templates文件夹     |  |-__init__.py文件     |  |-views.py文件     |-tmp文件夹     |-run.py文件 亲,想要运行这个程序么?那就运行这

  • Python的Flask框架中web表单的教程

     概要 在前面章节我们为主页定义了一个简单的模板,部分尚未实现的模块如用户或帖子等使用模拟的对象作为临时占位. 本章我们将看到如何利用web表单填补这些空白. web表单是web应用中最基本的构建要素,我们将通过表单来实现用户发帖和应用登录功能. 完成本章内容你需要基于前面章节完成的微博应用代码,请确认这些代码已安装并能正常运行. 配置 Flask-WTF是WTForms项目的Flask框架扩展,我们将用他来帮助我们处理web表单. 大部分Flask扩展都需要定义相关配置项,所以我们先来在应用根

  • Python的Flask框架中@app.route的用法教程

    在我上一篇文章,我搭了一个框架,模拟了Flask网站上"@app.route('/')"第一条例子的行为. 如果你错过了那篇"这不是魔法",请点击这里. 在这篇文章中,我们打算稍微调高点难度,为我们的URL加入可变参数的能力,在本文的最后,我们将支持下述代码段所期望达到的行为. app = Flask(__name__) @app.route("/hello/<username>") def hello_user(username):

  • Python的Flask框架中实现分页功能的教程

    Blog Posts的提交 让我们从简单的开始.首页上必须有一张用户提交新的post的表单. 首先我们定义一个单域表单对象(fileapp/forms.py): class PostForm(Form): post = TextField('post', validators = [Required()]) 下面,我们把这个表单添加到template中(fileapp/templates/index.html): <!-- extend base layout --> {% extends &

  • Python的Flask框架中的Jinja2模板引擎学习教程

    Flask的模板功能是基于Jinja2模板引擎来实现的.模板文件存放在当前目前下的子目录templates(一定要使用这个名字)下. main.py 代码如下: from flask import Flask, render_template app = Flask(__name__) @app.route('/hello') @app.route('/hello/<name>') def hello(name=None): return render_template('hello.html

  • Python的Flask框架中Flask-Admin库的简单入门指引

    Flask-Admin是一个功能齐全.简单易用的Flask扩展,让你可以为Flask应用程序增加管理界面.它受django-admin包的影响,但用这样一种方式实现,开发者拥有最终应用程序的外观.感觉和功能的全部控制权. 本文是关于Flask-Admin库的快速入门.本文假设读者预先具有一些Flask框架的知识. 介绍 初始化 增加视图 身份验证 生成URL 模型视图 文件管理 介绍 这个库打算做到尽可能的灵活.并且开发者不需要任何猴子补丁就可以获得期望的功能. 这个库使用一个简单而强大的概念-

  • Python的Flask框架中实现简单的登录功能的教程

     回顾 在前面的系列章节中,我们创建了一个数据库并且学着用用户和邮件来填充,但是到现在我们还没能够植入到我们的程序中. 两章之前,我们已经看到怎么去创建网络表单并且留下了一个实现完全的登陆表单. 在这篇文章中,我们将基于我门所学的网络表单和数据库来构建并实现我们自己的用户登录系统.教程的最后我们小程序会实现新用户注册,登陆和退出的功能. 为了能跟上这章节,你需要前一章节最后部分,我们留下的微博程序.请确保你的程序已经正确安装和运行. 在前面的章节,我们开始配置我们将要用到的Flask扩展.为了登

  • Python的Flask框架中集成CKeditor富文本编辑器的教程

    CKeditor是目前最优秀的可见即可得网页编辑器之一,它采用JavaScript编写.具备功能强大.配置容易.跨浏览器.支持多种编程语言.开源等特点.它非常流行,互联网上很容易找到相关技术文档,国内许多WEB项目和大型网站均采用了CKeditor. 下载CKeditor 访问CKeditor官方网站,进入下载页面,选择Standard Package(一般情况下功能足够用了),然后点击Download CKEditor按钮下载ZIP格式的安装文件.如果你想尝试更多的功能,可以选择下载Full

  • 在Python的Flask框架中实现单元测试的教程

     概要 在前面的章节里我们专注于在我们的小应用程序上一步步的添加功能上.到现在为止我们有了一个带有数据库的应用程序,可以注册用户,记录用户登陆退出日志以及查看修改配置文件. 在本节中,我们不为应用程序添加任何新功能,相反,我们要寻找一种方法来增加我们已写代码的稳定性,我们还将创建一个测试框架来帮助我们防止将来程序中出现的失败和回滚. 让我们来找bug 在上一章的结尾谈到,我故意在应用程序中引入一个bug.接下来让我描述一下它是什么样的bug,然后看看当我们的程序不按照我们意愿执行的时候,它在其中

  • Python的Flask框架中使用Flask-SQLAlchemy管理数据库的教程

    使用Flask-SQLAlchemy管理数据库 Flask-SQLAlchemy是一个Flask扩展,它简化了在Flask应用程序中对SQLAlchemy的使用.SQLAlchemy是一个强大的关系数据库框架,支持一些数据库后端.提供高级的ORM和底层访问数据库的本地SQL功能. 和其他扩展一样,通过pip安装Flask-SQLAlchemy: (venv) $ pip install flask-sqlalchemy 在Flask-SQLAlchemy,数据库被指定为URL.表格列出三个最受欢

随机推荐