利用pycharm学习flask(七)

本文内容

1.自定义错误页面
2.链接
3.静态文件
4.使用flask-moment

自定义错误页面

在hello.py添加

1
2
3
4
5
6
7
@app.errorhandler(404)
def page_not_found(e):
return render_template('404.html'),404

@app.errorhandler(500)
def internal_server_error(e):
return render_template('500.html'),500

和视图函数一样,错误处理程序也会返回响应,同时还返回与该错误对应的数字状态码。

错误处理程序中引用的模板也要编写,编写这些模板最直观的方法是复制templates/user.html,分别创建templates/404.html和templates/500.html,然后把这两个文件中的页面头部元素改为相应的错误消息。但这种方法带来很多重复劳工。

我们可以使用Jinja2的模板继承来解决这个问题,在pycharm中新建一个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
{% 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">
{% block page_content %}{% endblock %} </div>
{% endblock %}

这是一个继承自bootstrap/base.html的新模板,这个模板也可以作为其他模板的基模板,例如templates/user.html、templates/404.html、templates/500.html。

这个模板的content块中只有一个div容器,其中包含了一个page_content的新的空块,块中的内容由衍生模板定义。

现在程序使用的模板继承自这个base模板,而不是flask-bootstrap的基模板。

在pycharm中新建templates/404.html:

1
2
3
4
5
6
{% extends "base.html" %}
{% block title %}Flasky - Page Not Found{% endblock %}
{% block page_content %} <div class="page-header">
<h1>Not Found</h1>
</div>
{% endblock %}

之后访问一个不存在的页面就会如图所示:

我们还可以修改templates/user.html来继承这个基模板达到简化代码的作用:

1
2
3
4
5
6
7
{% extends "base.html" %}
{% block title %}Flasky{% endblock %}
{% block page_content %}
<div class="page-header">
<h1>Hello, {{ name }}!</h1>
</div>
{% endblock %}

链接

任何具有多个路由的程序都需要可以连接不同页面的链接,例如导航条。
在模板中直接编写简单路由的 URL 链接不难,但对于包含可变部分的动态路由,在模板 中构建正确的 URL 就很困难。而且,直接编写 URL 会对代码中定义的路由产生不必要的 依赖关系。如果重新定义路由,模板中的链接可能会失效。

为了避免这些问题,Flask 提供了 url_for() 辅助函数,它可以使用程序 URL 映射中保存 的信息生成 URL。url_for() 函数最简单的用法是以视图函数名(或者 app.add_urlroute() 定义路由时使用 的端点名)作为参数,返回对应的 URL。例如,在当前版本的 hello.py 程序中调用 url for(‘index’)得到的结果是/。调用url_for(‘index’, _external=True)返回的则是绝对地 址,在这个示例中是 http://localhost:5000/

使用 url_for() 生成动态地址时,将动态部分作为关键字参数传入。例如,url_for (‘user’, name=’john’, _external=True)的返回结果是http://localhost:5000/user/john

传入 url_for() 的关键字参数不仅限于动态路由中的参数。函数能将任何额外参数添加到 查询字符串中。例如,url_for(‘index’, page=2)的返回结果是/?page=2。

静态文件

默认设置下,Flask 在程序根目录中名为 static 的子目录中寻找静态文件。如果需要,可在 static 文件夹中使用子文件夹存放文件。服务器收到前面那个 URL 后,会生成一个响应, 包含文件系统中 static/css/styles.css 文件的内容。

修改templates/base.html:

1
2
3
4
5
6
7
{% block head %}
{{ super() }}
<link rel="shortcut icon" href="{{ url_for('static', filename = 'favicon.ico') }}"
type="image/x-icon">
<link rel="icon" href="{{ url_for('static', filename = 'favicon.ico') }}"
type="image/x-icon">
{% endblock %}

图标的声明会插入 head 块的末尾。注意如何使用 super()保留基模板中定义的块的原始内容。

使用Flask-Moment本地化日期和时间

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

有一个使用JavaScript开发的优秀客户端开源代码库,名为 moment.js(http://momentjs.com/) ,它可以在浏览器中渲染日期和时间。Flask-Moment 是一个 Flask 程序扩展,能把moment.js集成到Jinja2模板中。这里我们使用Flask-Moment来本地化日期和时间,在pycharm中preferences中的project interpreter中安装Flask-Moment插件。

除了moment.js,Flask-Moment还依赖jquery.js。要在HTML文档的某个地方引入这两个库,可以直接引入,这样可以选择使用哪个版本,也可使用扩展提供的辅助函数,从内容 分发网络(Content Delivery Network,CDN)中引入通过测试的版本。Bootstrap已经引入了 jquery.js,因此只需引入moment.js即可。

修改templates/base.html:

1
2
3
4
{% block scripts %}
{{ super() }}
{{ moment.include_moment() }}
{% endblock %}

注意,此处代码一定要加在最后,至此我的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
43
44
45
46
47
{% extends "bootstrap/base.html" %}

{% block title %}
Flasky
{% endblock %}

{% block head %}
{{ super() }}
<link rel="shortcut icon" href="{{ url_for('static', filename = 'favicon.ico') }}"
type="image/x-icon">
<link rel="icon" href="{{ url_for('static', filename = 'favicon.ico') }}"
type="image/x-icon">
{% 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 %}

首页截图应如下:

坚持原创技术分享,您的支持将鼓励我继续创作!