3.1 Jinja2模板引擎
个人觉得模板主要用于前端的显示部分。模板中用到python语句的地方,需要用{% %}包围起来,并且有开始和结束两行,而变量名则需要用两个大括号包围:{{ }}。如下面为一个条件控制语句:
{% if user %} Hello,{{ user }}! {% else %{# for message in messages #}
上面代码中的for循环将被注释掉而不会被执行
3.1.1 渲染模板
Jinja2是Flask默认使用的模板引擎。默认情况下,Flask程序在程序文件夹中的templates子文件夹中寻找模板。简单的模板使用示例:
from flask import Flask render_template app = Flask(__name__) @app.route('/') def index(): return render_template(index.html/user/<name> user(name): user.html',name=name) if __name__ == __main__: app.run()
如上,render_template函数的第一个参数是模板的文件名,后面的参数都是键值对,表示模板文件中接收的变量。如上的user()函数中,将会把name传给user.html文件。
最简单的user.html文件(位置为templates/user.html)可以是:
<h1>Hello,{{ name }}!</h1>
由此,通过user()函数传入的name参数将会在模板中的相应位置显示
3.1.2 变量
Jinja2可以识别所有类型的变量,包括列表、字典、对象。也可以使用过滤器修改变量,变量名和过滤器之间使用竖线分隔。如下述模板以首字母大写形式显示变量name的值:
Hello,{{ name|capitalize }}
以下是Jinja2提供的部分常用的过滤器:
过滤器名 说明 safe 渲染值时不转义 capitalize 把值的首字母转换成大写,其它字母转换成小写 lower 把值转换成小写形式 upper 把值转换成大写形式 title 把值中每个单词的首字母都转换成大写 trim 把值的首尾空格去掉 striptags 渲染之前把值中所有的HTML标签都删掉
值得注意的是safe过滤器。默认情况下,Jinja2会转义所有变量。如果把 '<h1>Hello</h1>'转换成'<h1>Hello</h1>',如果需要显示变量中存储的HTML代码,就可以使用safe过滤器,但千万不要在不可信的值上使用safe过滤器。 完整的过滤器列表在:Template Designer Documentation
3.1.3 控制结构
Jinja2的控制结构与一般编程语言的控制语句有点类似。
- 条件控制语句
{%
<ul>
{% for comment in comments %}
<li>{{ comment }}</li>
{% endfor %}
</ul>
- 使用宏
定义宏 {% macro render_comment(comment) %} <li>{{ comment }}</li> {% endmacro %} 使用宏 <ul>} {{ render_comment(comment) }} {% endfor %} </ul>
还可以将其写入单独的文件中,以避免重复:
{% include common.html' %}
- 模板继承
模板继承类似于Python中的类继承。先写一个名为base.html的基模板:
<html> <head> {% block head %} <title>{% block title %}{% endblock %} - My Application</title> {% endblock %} <body> {% block body %} {% endblock %} </body> </head> </html>
如上,在block标签中的元素是可以在衍生模板中修改的,如:
{% extends "base.html" %} {% block title %}Index{% endblock %} {% block head %} {{ super() }} <style> </style> {% endblock %} {% block body %} <h1>Hello,World!</h1> {% endblock %}
extends指令声明这个模板衍生自base.html。其后基模板中的3个块title、head、body被重新定义。
注意在新定义的head块中,因为在基模板中其内容不是空的,所以要使用super()来获取原来的内容
模板中的所有block都必须要有结束的block语句
3.2 使用Flask-Bootstrap集成Twitter Bootstrap
Bootstrap是一个前端的js框架,可以用创建优雅的UI。可以使用pip安装:(venv) $ pip install flask-bootstrap
初始化Flask-Bootstrap
在代码中加入:
原书中的代码是 from flask.ext.bootstrap import Bootstrap # 但是我在python3.5中运行时,被提示说这种用法已经过时了 而应该使用下面这种导入方法 from flask_bootstrap Bootstrap ... 下面这行代码应在app = Flask(__name__)之后 bootstrap = Bootstrap(app) ...
- 在模板中使用Flask-Bootstrap
修改templates/base.html文件:
{% extends bootstrap/base.html} {% block title %}Flasky{% endblock %} {% block navbar %} <div class=navbar navbar-invrese" role=navigation"> <div container"> <div navbar-header"> <button type=button" navbar-toggle" data-toggle=collapse" data-target=.navbar-collapse"> <span sr-only">Toggle navigation</span> <span icon-bar"></span> <span "></span> </button> <a navbar-brand" href=">Flasky</a> </div> <div navbar-collapse collapse"> <ul nav navbar-nav"> <li><a href=">Home</a></li> </ul> </div> </div> </div>} {% block content %page-header"> <h1>Hello,{{ name }}!</h1> </div> </div> {% endblock %}
3.3 自定义错误页面
在没有定义错误页面之前,如果访问一个不存在的URL,浏览器会显示一个它内置的404页面。
Flask提供了errorhandler()修饰器,允许程序自定义错误页面。如下两段代码可以指定特定的404和500错误页面:
@app.errorhandler(404 page_not_found(e): 404.html'),404 @app.errorhandler(500 internal_server_error(e): 500.html{% extends navbar navbar-inverse"> {% block page_content %}{% endblock %} </div> {% endblock %}
基模板主要定义了默认标题和导航栏内容,内容部分content block只放了一个div,其中包含了一个名为page_content的空白块,块中的内容由衍生模板定义,作为页面主体内容显示。
由此重新组织的templates/user.html页面为:
{% extends } {% block page_content %"> <h1>Hello,{{ name }}!</h1> </div> {% endblock %}
404错误页面templates/404.html
{% extends } {% block title %}Flasky - Page Not Found{% endblock %"> <h1>Not Found</h1> </div> {% endblock %}