模板
春花不红不如草,少年不美不如老。
为什么引入模板的概念
例如用户在网站中注册了一个新账户,用户在表单中输入电子邮件地址和密码.点击提交按钮。服务器收到包含用户输入数据的请求。然后 Flask 把请求分发到处理注册请求的视图函数.这个视图函数需要访问数据库,添加新用户,然后生成响应回送浏览器.这两个过程分别是业务逻辑层和表现逻辑
把表现逻辑移到模板中能够提升程序的可维护性
模板是一个包含响应文本的文件,其中包含用占位变量表示的动态部分,其具体值只在请求的上下文中才能知道,使用真实值替换变量,再返回最终得到的响应字符串,这一过程称为渲染.为了渲染模板 Flask 使用了一个名为 Jinja2 的强大的模板引擎
Jinja2 模板引擎
- 形式最简单的 Jinja2 模板就是一个包含响应文本的文件.
<h1>Hello {{name}}!</h1>
渲染模板
默认情况 Flask 在程序文件夹中的 templates 子文件夹中寻找模板.在下一个 hello.py 版本中要把前面定义的模板保存在 templates 文件夹中,并分别命名为 index.html 和 user.html
from flask import Flask,render_template
@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 模板引擎集成到了程序中.render_template 函数的第一个参数是模板的文件名,随后的参数都是键值对,表示模板中变量对应的真实值.在这段代码中,第二个模板收到一个名为 name 的变量
上例中 name=name 是关键字参数,这类关键字参数很常见,左边 name 表示参数名,就是模板中的占位符,右边的 name 就是当前作用域的变量,表示同名参数的值
变量
示例中在模板使用的结构表示一个变量,它是一种特殊的占位符,告诉模板这个位置的值从渲染模板时使用的数据获取
Jinja2 能识别所有类型的变量,甚至是一些复杂的类型,例如列表,字典,和对象.在模板中使用变量的一些示例
<p> value from a dictionary {{mydict['key']}}</p>
<p> value from a list:{{mylist[3]}}</p>
<p> value from a list ,with a variable index:{{mylist[myintvar]}}</p>
<p> value from an object method:{{myobj.somemethod()}}</p>
- 也可以使用过滤器修改变量,过滤器名添加在变量名之后,中间使用竖线分割.例如下述模板以首字母大写形式展现变量 name 的值
Hello, {{name|capitalize}}
过滤器变量名 | 说明 |
---|---|
safe | 渲染值时不转义 |
capitalize | 把值的首字母转换成大写, 其他字母转换成小写 |
lower | 把值转变成小写 |
upper | 把值转变成大写 |
title | 把值中每个单词的首字母都转换成大写 |
trim | 把值的首尾空格去掉 |
striptags | 渲染之前把值中所有的 HTML 标签都删掉 |
特别说明的是 safe 默认情况下 出于安全考虑 Jinja2 会转义所有的变量,例如一个变量值是’
hello
‘ 它会把小于 大于号都转变类似 < 之类的,很多情况下需要显示变量中存储的 HTML 代码,这个时候可使用 safe 过滤器
控制结构
- 在模板中使用条件控制语句
{% if user %}
Hello ,{{user}}123
{% else %}
Hello Stranger!
{% endif %}
- for 循环实现调用
<ul>
{% for comment in comments %}
<li>{{comment}}</li>
{% endfor %}
</ul>
- 如果需要重复使用的话
{% include 'common.html' %}
- 模板继承,创建一个名为 base.html 模板
<html>
<head>
{% block head %}
<title>{% block title %}{% endblock %} - MyApplication</title>
{% endblock %}
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html></title>
block 标签我们定义了名为 head ,title,body 的块
{% extends 'base.html' %}
{% block title %}Index{% endblock %}
{% block head %}
{{super()}}
<style>
</style>
{% endblock %}
{% block body %}
<h1>Hello,world</h1>
{% endblock %}
extends 指令声明这个模板衍生自 base.html 在 extends 指令后,基础模板中的 3 个块被重新定义,模板引擎会将其插入适当的位置.在重新定义新的 head 块,在基础模板中 内部不是空的,所以使用 super()来继承
链接
为了避免这些问题,Flask 提供了 url_for()辅助函数,它可以在程序 URL 映射中保存信息生成的 URL
url_for() 函数最简单的用法是以视图函数名左外参数,返回对应的 url 比如
@app.route('/hi')
def hello:
return 'haha'
@app.route('/testurlfor')
def testurl:
print(url_for('hello'),_external=True)
# 这样返回的就是绝对地址 http:localhost:5000/hi 特别注意的就是参数是函数名而不是路由
静态文件
- 比如说引入图片 css 之类的,可以通过 url_for 来引用比如
url_for('static',filename='css/style.css',_external=True)
# 得到的结果
# http://localhost:5000/static/css/style.css
- 默认设置下 Flask 在程序根目录中名为 static 的子目录中寻找静态文件.如果需要,可在 static 文件夹中使用子文件夹放文件.服务器收到前面那个 URL 后,会生成一个响应,包含文件系统中 static/css/styles.css
{% block head %}
<link rel="shortcut icon" href="{{url_for('static',filename='favicon.ico')}}" type="image/x-icon">
{% endblock %}
使用 Flask-Moment 本地化时间和日期(了解就好)
要想在服务器上只使用 UTC 时间。有一个使用 JS 开发的优秀客户端开源代码库,名为 moment.js 它可以在浏览器中渲染日期和时间。Flask-Moment 是一个 Flask 程序扩展,能把 moment.js 集成到模板中 Flask-Moment 可以使用 pip 安装
pipenv install flask-moment
- 初始化 Flask-monent
from flask.ext.moment import Moment
moment = Moment(app)
除了 moment.js 还必须依赖 jquery.js,页面上必须写 jquery.js
{% block scripts %}
{{super()}}
{{moment.include_moment()}}
{% endblock %}