前言
在上一篇 Flask开发Day1-Hello world中,我们已经创建好了一个Flask应用,接下来,我们就会针对他进行功能的添加,实现出一个中小型项目的web应用。
动态用户显示
这个功能想要实现的是:根据不同用户显示出不同的欢迎界面
假设我们现在需要有一个欢迎用户的标题。虽然目前的应用程序还没有实现用户概念(需要与数据库打交道),但这不妨碍我使用一个Python字典来模拟一个用户。
1 | user = {'username': 'Tom'} |
代码编写如下:
1 | from app import app |
- 注意,要在html 代码中嵌入其他内容,需要使用三引号进行包裹。
页面效果:
那么问题来了,功能的确是实现了,但是以后网页的维护怎么办? 我是指,当以后网页的用户变多了,我们总不可能在一张网页里写出所有用户的信息吧?而且如果哪天我决定更改这个应用的布局,那就不得不更新每个视图函数的HTML字符串。显然,随着应用的扩张,这种“写死”的方式完全不可行。
模板的实现
模板有助于实现页面展现和业务逻辑之间的分离。脚本这块,负责逻辑的实现,而页面渲染的内容,交个html文件,这样就实现了前后端分离操作。
一张模板就相当于一个函数,我们可以不断调用它,从而实现渲染多个页面的效果,减轻了代码的重复性,也便于后期的修改(更改一处,处处改变)。
在Flask中,模板被编写为单独的文件,存储在应用程序包内的templates文件夹中。 在确定你在microblog目录后,创建一个存储模板的目录:
1 | (venv) $ mkdir app/templates |
在下面可以看到你的第一个模板,它的功能与上面的index()
视图函数返回的HTML页面相似。 把这个文件写在app/templates/index.html中:
1 | <html> |
- 双花括号里面包含的内容是动态获取的,通过这种形式,我们可以获取到函数传入的参数。
渲染模板
网页渲染转移到HTML模板之后,视图脚本(routes.py)就能被简化:
1 | from flask import render_template |
- 将模板转换为完整的HTML页面的操作称为渲染。 我们需要从Flask框架中导入一个名为
render_template()
的函数。 render_template()
函数调用Flask框架原生依赖的Jinja2模板引擎。它需要传入渲染的页面,还有变量参数列表(会替换模板中双花括号里面的代码块)- 对比起之前return的一大串html代码,这样是不是更简洁呢? 更重要的是,这个模板是可以多次使用的
jinja2
在渲染过程中使用实际值替换占位符,只是Jinja2在模板文件中支持的诸多强大操作之一。
条件判断:
1 | <html> |
- 以上通过条件判断书写了两种情况的 title 显示(开始有了动态的感觉)
- 在jinja2中,通过特定格式传入控制语句,其他的还有 for循环、过滤器、分隔符等等,其方法格式在官网上都有,有兴趣的可以去官网学习:http://docs.jinkan.org/docs/flask/
模板继承
我们可能在平常的网页中可能会看到这么个情况:例如豆瓣评分,页面的框架大多相同,变化的只是其中呈现的内容,那么框架相同则意味着相同的代码,我们有没有一种方法,使得模板中也可以互相共用代码?
Jinja2有一个模板继承特性,专门解决这个问题。从本质上来讲,就是将所有模板中相同的部分转移到一个基础模板中,然后再从它继承过来。
例如,我们现在编写一个base.html基础文件:
1 | <html> |
- 这里比较陌生的代码可能就是那个block关键字了。在jinja2中 block被赋予一个唯一的名称,派生的模板可以在提供其内容时进行引用。(就像HTML中link标签用来引入css文件一样)
- block content 是一种固定写法,它让Jinja2知道如何将这模板合并成在一起。
有了基础文件之后,我们就可以修改index.html,在其中渲染base.html文件
1 | {% extends "base.html" %} |
extends
语句用来建立了两个模板之间的继承关系,后面跟着的渲染模板的文件- 这里block content里面出现的HTML代码就会当成附加内容,渲染到base.html里的block代码块中。
页面效果:
写在最后
需要注意的是,如果网页出现以下内容:
- 可能就是你的代码书写错误,好好回想自己干了什么,然后去代码中看看
- 大多数情况下,都是jinja2语法错误,在templates/xxx.html 各种文件中,它的注释有独特的写法(详见官方文档),如果使用HTML的
<!-- -->
就会出现以上报错(碰到的坑)