利用pycharm学习flask(七)
本文内容
1.自定义错误页面
2.链接
3.静态文件
4.使用flask-moment
自定义错误页面
在hello.py添加
@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,内容如下:
{% 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:
{% 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来继承这个基模板达到简化代码的作用:
{% 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_url_route() 定义路由时使用 的端点名)作为参数,返回对应的 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:
{% 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:
{% block scripts %}
{{ super() }}
{{ moment.include_moment() }}
{% endblock %}
注意,此处代码一定要加在最后,至此我的base.html完整代码如下:
{% 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 %}
首页截图应如下: