Flask 教程,第二部分:模板 已翻译 100%

oschina 投递于 2012/12/28 08:54 (共 13 段, 翻译完成于 01-06)
阅读 73419
收藏 25
9
加载中

本系列文章是我用Python框架Flask开发Web应用的经验记录.这是第二篇.

该系列文章的目的是建立一个功能完善的微博应用,我决定称它为microblog,虽然这个名字没什么创意. ^_^

一下是该系列所有已发布文章的索引:

 

栗子太重举不动
栗子太重举不动
翻译于 2012/12/31 13:49
4

概述

如果你已经阅读过上一个章节,那么你应该已经完成了充分的准备工作并且创建了一个很简单的具有如下文件结构的Web应用:

microblog
    |-flask文件夹
    |-<一些虚拟环境的文件>
    |-app文件夹
    |  |-static文件夹
    |  |-templates文件夹
    |  |-__init__.py文件
    |  |-views.py文件
    |-tmp文件夹
    |-run.py文件

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

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

栗子太重举不动
栗子太重举不动
翻译于 2012/12/31 14:14
4

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

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

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

要显示一个美观大方的标题,最简单的方法就是改变我们提供视图的方式来显示一些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>

现在,在你的浏览器里面刷新一下看看,是不是很爽?

栗子太重举不动
栗子太重举不动
翻译于 2012/12/31 14:30
3

因为我们这个小程序还支持用户功能,所以咱用了一个用户占位对象,通常它被亲切的称呼为假数据或测试数据。它可以让我们关注程序中急需解决的部分。

爽完了,面对实际吧,我希望你会觉得上面这个混合着html代码的小程序相当恶心。想想看,如果你用一些动态内容生成的一个复杂的HTML页面,并且想要在由这样的程序组成的网站中改变一些页面内容,这将会一件非常蛋疼的事情。

zzxworld
zzxworld
翻译于 2013/01/05 16:15
4

模板系统拯救世界

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

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

<html>
  <head>
    <title>{{title}} - microblog</title>
  </head>
  <body>
      <h1>Hello, {{user.nickname}}!</h1>
  </body>
</html>
如你所见,我们只是写了一个普通的HTML页面,唯一跟HTML有区别的就是里面掺杂了一些以 {{ ... }} 组成的动态内容占位符。
zzxworld
zzxworld
翻译于 2013/01/05 16:37
4

现在让我们来看看视图函数中是如何处理这个模板的(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 用导入的变量替换掉了模板中对应的 {{ ... }} 代码块。

zzxworld
zzxworld
翻译于 2013/01/05 17:38
2

模板中的流程控制

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 流程语句是如何工作的。
zzxworld
zzxworld
翻译于 2013/01/05 23:13
2

模板中使用循环

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

首先,创建用户和文章 (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可以隐射为表的一个字段,这里为了给大家演示模板的使用,没有使用数据库相关的技术,简单地使用字典和数组模拟用户和他的好友最近发表的文章。

pengfei_xue
pengfei_xue
翻译于 2013/01/06 12:13
5

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

要解决这个问题,就需要一个新的流程控制语句: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>
很简单吧,你还可以在数组中添加更多的内容看看效果。
zzxworld
zzxworld
翻译于 2013/01/06 13:52
5

模板继承

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

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

zzxworld
zzxworld
翻译于 2013/01/06 14:17
3
本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。
我们的翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。
加载中

评论(6)

Pandao
Pandao
翻译出自哪里
j
jamshulo

引用来自“述而不作”的评论

@zzxworld
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>
末尾应该是少了'''
是少了'''。
林客
林客
伟哥不错啊!
述而不作
述而不作
@zzxworld
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>
末尾应该是少了'''
ForEleven
ForEleven
注解配置路由,nice
沙发迪
沙发迪
好东西,支持!
返回顶部
顶部