本文主要整理下几个 Flask 扩展:

0.Flask-Bootstrap:集成 Twitter 开发的一个开源框架 Bootstrap

1.Flask-Script:为 Flask 程序添加一个命令行解析器

2.Flask-Moment:本地化日期和时间

本篇基于前两篇博文,需要使用虚拟环境、使用 pip 安装 Flask 等。

什么是扩展

Flask 被设计为可扩展形式,故而没有提供一些重要的功能,例如数据库和用户认证,所以我们可以选择最适合的程序的包,或者按需求自行开发。

说白了扩展就是一些附加功能,独立完成某种功能。

Flask-Bootstrap

Bootstrap 是 Twitter 开发的一个开源框架,它提供的用户界面组件可用于创建整洁且具有吸引力的网页,而且这些网页还能兼容所有现代 Web 浏览器。

Bootstrap 是客户端框架,因此不会直接涉及服务器。

服务器需要做的指示提供引用了 Bootstrap 层叠样式表( CSS )和 Javascript 文件的 HTML 响应,并在 HTML、CSS 和 JavaScript 代码中实例化所需组件。这些操作最理想的执行场所就是模板

安装 Flask-Bootstrap 扩展

1
pip install flask-bootstrap

创建 app.py 文件

1
2
3
4
5
6
7
8
9
10
11
12
from flask import Flask,render_template
from flask.ext.bootstrap import Bootstrap
app = Flask(__name__)
bootstrap = Bootstrap(app)#注意这个地方
@app.route('/')
def index():
return render_template('index.html')
if __name__ == "__main__":
app.run(debug = True)

解释下:

0.from flask.ext.bootstrap import Bootstrap:专为 Flask 开发的扩展都暴露在 flask.ext 命名空间下,Flask-Bootstrap 输出了一个 Bootstrap 类。

1.bootstrap = Bootstrap(app):Flask 扩展一般都在创建程序实例时初始化,这行代码是 Flask-Bootstrap 的初始化方法。

创建 templates 文件夹并创建 base.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{% extends "bootstrap/base.html" %}
{% block title %}Flask{% 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">
{% block page_content %}{% endblock %}
</div>
{% endblock %}

解释下:

0.{% extends "bootstrap/base.html" %}:base.html 模板继承自 bootstrap/base.html

1.其中 titlenavbarcontent都是 bootstrap/base.html中定义的块(还有 script 等)。navbar 是显示导航栏。其中的代码比较多,作用是添加 Flasky 和 Home 两个链接,理解下即可。

2.page_content块是自己加的。

3.以后的 html 页面直接继承 base.html 就可以啦。

创建 index.html

index.html 中写入:

1
2
3
4
5
6
7
{% extends "base.html" %}
{% block title %}首页{% endblock %}
{% block page_content %}
<h1>这里是首页,Hello World!</h1>
{% endblock %}

解释下:

0.{% extends "base.html" %} :继承自 base.html

1.page_content 块就是上面的自己定义的块。

运行程序

显示如下:

运行结果.png

Flask-Script

Flask 的开发 Web 服务器支持很多启动设置选项,但只能在脚本中作为参数传给app.run()函数。这种方式很不方便,传递设置选项的理想方式是使用命令行参数。

Flask-Script 就是这么一个 Flask 扩展,为 Flask 程序添加一个命令行解析器。Flask-Script 自带了一组常用选项,而且还支持自定义命令。

安装 Flask-Script 扩展

1
pip install flask-script

修改 app.py 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
from flask import Flask,render_template
from flask.ext.bootstrap import Bootstrap
from flask.ext.script import Manager
app = Flask(__name__)
manager = Manager(app)#注意这个地方
@app.route('/')
def index():
return render_template('index.html')
if __name__ == "__main__":
manager.run()#注意这个地方

解释下:

0.from flask.ext.script import Manager:Flask-Script 输出了一个名为 Manager 的类,同样也是 flask.ext.XXX 下。

1.manager.run() 代替了 app.run(),启动后就能解析命令行啦。

使用 Flask-Script

0.运行 app.py :python app.py

1. Flask-Script 官方文档

Flask-Moment

服务器需要统一时间单位,这和用户所在的地理位置无关,所以一般使用协调世界时间(Coordinated Universal Time, UTC)。用户不愿意看到 UTC 时间,他们更希望看到当地时间,而且采用当地惯用的格式。

要想在服务器上只使用 UTC 时间,一个优雅的解决方案是,把时间单位发送给 Web 浏览器。转换成当地时间,然后渲染。Web 浏览器可以更好的完成这一任务,因为它能获取用户电脑中的时区和区域设置。

有一个使用 JavaScript 开发的优秀客户端开源代码,名为 moment.js (http://momentjs.com/),它可以在浏览器中渲染日期和时间。

安装 Flask-Moment 扩展

1
pip install flask-moment

修改 app.py 文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
from flask import Flask,render_template
from flask.ext.bootstrap import Bootstrap
from flask.ext.script import Manager
from flask.ext.moment import Moment
from datetime import datetime
app = Flask(__name__)
manager = Manager(app)
bootstrap = Bootstrap(app)
moment = Moment(app)
@app.route('/')
def index():
return render_template('index.html',current_time=datetime.utcnow())
if __name__ == "__main__":
manager.run()

解释下:

0.from flask.ext.moment import Moment:导入一个 Moment 类

1.from datetime import datetime:导入一个 datetime 类,用于获取 UTC 时间

2.moment = Moment(app):向模板开放了 Moment 类,可以在模板中使用

3.current_time=datetime.utcnow():获取当前 UTC 时间,作为参数传入index.html

修改 base.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
{% extends "bootstrap/base.html" %}
{% block title %}Flask{% 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">
{% block page_content %}{% endblock %}
</div>
<!--注意下方block script-->
{% block scripts %}
{% raw %}{{ super() }}{% endraw %}
{% raw %}{{ moment.include_moment() }}{% endraw %}
{% endblock %}
{% endblock %}

解释下:

0.除了 moment.js ,Flask-Moment 还依赖 jquery.js 。但是 Bootstrap 中已经引入了 jquery.js ,故只需要引入 moment.js

1.{{ moment.include_moment() }} :引入 moment.js,请注意上方的{{ super() }}

修改 index.html

1
2
3
4
5
6
7
8
9
10
11
{% extends "base.html" %}
{% block title %}首页{% endblock %}
{% block page_content %}
<h1>这里是首页,Hello World!</h1>
<p>{{ moment(current_time).format('LLL') }}</p>
<p>{{ moment(current_time).fromNow(refresh=True) }}</p>
{% endblock %}

解释下:

0.{{ moment(current_time).format('LLL') }}:根据客户端电脑中的时区和区域设置渲染日期和时间。参数决定了渲染的方式,’L’到’LLL’分别对应不同的复杂度。format()函数还可以接受自定义的格式说明符。

1.{{ moment(current_time).fromNow(refresh=True) }}moment是 app.py 开放的类,current_time 是 app.py 传递过来的参数,fromNow() 渲染相对时间戳,参数 refresh=True 会随着时间的推移自动刷新显示时间。

一个完整的 Demo

这个 Demo,包含上方未介绍到的东西:

0.url_for() 函数的使用
1.静态文件的引入:设置网页的小图标(如百度网页的那个小熊掌)
2.自定义 404 错误页面

创建文件夹,包含文件

文件夹结构如下:

1
2
3
4
5
6
7
8
9
10
--app
--app.py
--templates
--base.html
--index.html
--user.html
--404.html
--static
--favicon.png
--venv

app.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from flask import Flask,render_template
from flask.ext.bootstrap import Bootstrap
from flask.ext.script import Manager
from flask.ext.moment import Moment
from datetime import datetime
app = Flask(__name__)
manager = Manager(app)
bootstrap = Bootstrap(app)
moment = Moment(app)
@app.route('/')
def index():
return render_template('index.html',current_time=datetime.utcnow())
@app.route('/user/<name>')
def user(name):
return render_template('user.html',name=name)
@app.errorhandler(404)
def page_not_found(e):
return render_template('404.html'),404
if __name__ == "__main__":
manager.run()

base.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
{% extends "bootstrap/base.html" %}
{% block head %}
{{ super() }}
<link rel="shortcut icon" href="{{ url_for('static',filename = 'favicon.png') }}" type='image/x-icon'/>
<link rel="icon" href="{{ url_for('static',filename = 'favicon.png') }}" type="image/x-icon"/>
{% endblock %}
{% block title %}Flask{% 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">
{% block page_content %}{% endblock %}
</div>
{% block scripts %}
{{ super() }}
{{ moment.include_moment() }}
{% endblock %}
{% endblock %}

index.html

1
2
3
4
5
6
7
8
9
10
11
{% extends "base.html" %}
{% block title %}首页{% endblock %}
{% block page_content %}
<h1>这里是首页,Hello World!</h1>
<p>{{ moment(current_time).format('LLL') }}</p>
<p>{{ moment(current_time).fromNow(refresh=True) }}</p>
{% endblock %}

user.html

1
2
3
4
5
6
7
8
9
10
11
12
13
{% extends "base.html" %}
{% block title %}User{% endblock %}
{% block page_content %}
{% if name %}
<h1> Hello {{ name }} </h1>
{% else %}
<h1> Hello Stranger </h1>
{% endif %}
{% endblock %}

404.html

1
2
3
4
5
6
7
{% extends "base.html" %}
{% block title %} 404 {% endblock %}
{% block page_content %}
<h1> 404 错误:页面没有找到 </h1>
{% endblock %}

favicon.png

favicon.png