模板中的大概内容
以用户在网站中注册新账户的过程为例。用户在表单中输入电子邮件地址和密码,点击提交。于是,服务器接收到包含用户输入数据的请求,然后Flask把请求给处理注册请求的视图函数。这个视图再访问数据库,添加新用户,生成响应回送浏览器,指明操作是否成功。这两个过程分别为业务逻辑和表现逻辑。
把表现逻辑移到模板中能提升应用的可维护性。
模板是包含响应文本的文件,其中包含用占位变量表示的动态部分,其具体值只在请求的上下文中才知道。使用真实值替换变量,再返回最终得到的响应字符串,这一过程称为渲染,需要使用到 Jinja2 模板引擎。
2.1 Jinja2 模板引擎
2.2.1 渲染模板
- 默认情况下,flask在应用目录中的 templates 子目录里寻找模板。
例如:
templates/index.html
<h1>Hello World</h1>
templates/user.html
<h1>Hello, {{ name }}!</h1>
- 应用中的视图函数也需要修改一下:
app = Flask(__name__)
bootstrap = Bootstrap(app)
moment = Moment(app)
# 设置一个路由,就是处理url和函数之间(映射)关系的程序
@app.route('/')
def index():
return render_template('index.html')
@app.route('/user/<name>')
def user(name):
return render_template('user.html', name=name)
- flask 提供的 render_template() 函数把Jinja2模板引擎集成到了应用中
这个函数第一个参数是模板的文件名,随后的参数都是键值对,表示模板中变量对于的具体值。左边的 name表示参数名,即模板中使用的占位符,右边的name是当前作用域中的变量。
2.1.2 变量
模板中使用的 {{ name }}结构表示一个变量,告诉模板引擎这个位置的值从渲染模板时使用的数据中获取。
2.2 使用Flask-Bootstrap 集成 Bootstrap
Bootstrap 是一个开源web 框架。可以使用flask 的扩展。
我们使用 Flask-Bootstrap 的模板改写 templates/user.html
{% extends "bootstrap/base.html" %}
{% block title %}Flasky{% endblock %}
{% block navbar %}
<div class="navbar navbar-inverse" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle"
data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">Flasky</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/">Home</a></li>
</ul>
</div>
</div>
</div>
{% endblock %}
{% block content %}
<div class="container">
<div class="page-header">
<h1>Hello, {{ name }}!</h1>
</div>
</div>
{% endblock %}
- extends 指令,从Flask-Bootstrap 中导入 bootstrap/base.html,实现模板继承。base.html我们后面会讲。
- 上面user.html 模块定义了3个区块,分别名为 title,navbar和content。其中navbar区块使用Bootstrap组件定义了一个简单的导航栏。
- 我们可以得到这样的页面。看图我们的路由后部分是 /user/zzz:
2.3 自定义错误页面
如果在浏览器中输入无效的路由,我们应该返回错误页面
- 首先,我们使用装饰器为这两个错误处理定义函数。
以404错误为例:
@app.errorhandler(404)
def page_not_found(e):
return render_template('404.html'), 404
- 编写模板我们可以复制templates/user.html。但是,我们也也可定义一个具有统一页面布局的基模板,就是我们上面提到的 base.html。
templates/base.html :
<!-- 包含导航栏的应用基模板-->
{% extends "bootstrap/base.html" %}
{% block title %}Flasky{% endblock %}
{% block navbar %}
<div class="navbar navbar-inverse" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle"
data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">Flasky</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/">Home</a></li>
</ul>
</div>
</div>
</div>
{% endblock %}
{% block content %}
<div class="container">
<div class="page-header">
{% block page_content %}{% endblock %}
</div>
</div>
{% endblock %}
- 所以我们可以用模板继承机制自定义404错误页面了
templates/404.html
{% extends "base.html" %}
{% block title %}Flasky - Page Not Found{% endblock %}
{% block page_content %}
<div class="container">
<h1>Not Found</h1>
</div>
{% endblock %}
它就会在 page_content内容中显示 Not Found
2.4 链接
对于包含可变部分的动态路由,在模板中构建正确的URL很困难。因此,Flask 提供了 url_for() 函数,它使用应用的URL映射中保存的信息生成URL。
- url_for() 函数最简单的用法是以视图函数名作为参数,返回对应的URL。例如,在当前版本调用url_for(‘index’)得到的结果是/ ,即应用的根URL。调用url_for(‘index’, _external=True),返回的则是绝对地址,在我们的示例中是 http://localhost:5000/。
- 使用url_for()生成动态URL时,将动态部分作为关键字参数传入。例如 ,url_for(‘user’, name=‘zzz’, _external=True) 的返回结果是 localhost:5000/user/zzz。
- 非动态的参数也可以添加到查询字符串中。例如,url_for(‘user’, name=‘zzz’, page=2, version=1) 的返回结果是 /user/zzz?page=2&version=1