Flask_0x02 模板
0x1 Jinja2
1.1 Jinja2模板引擎
模板是包含响应文本的文件,其中包含用站位变量表示的动态部分
templates/user.html
<h1>Hello, {{ name }}!</h1>
Flask提供render_template函数把Jinja2模板引擎集成到程序中
渲染模板
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)
Jinja2能识别所有类型的变量
<p>A value from a dictionary: {{ mydict['key'] }}.</p>
<p>A value from a list: {{ mylist[3] }}.</p>
<p>A value from a list,with a variable index: {{ mylist[myintvar] }}.</p>
<p>A value from an object's method: {{ myobj.somemethod() }}.</p>
可以使用过滤器修改变量
Hello,{{ name|capitalize }}
Jinjia2变量过滤器:http://jinja.pocoo.org/docs/2.9/templates/#builtin-filters
safe 渲染值时不转义
capitalize 首字母大写,其他小写
lower 转换小写
upper 转换大写
title 把值中每个单词首字母转换成大写
trim 去掉值的首尾空格
striptags 渲染前把值中所有HTML标签删掉
1.2 控制结构
{% if user %}
Hello, {{ user }}
{% else %}
Hello, Stranger!
{% endif %}
<ul>
{% for comment in comments %}
<li>{{ comment }}</li>
{% endfor %}
</ul>
宏
{% macro render_comment(comment) %}
<li>{{ comment }}</li>
{% endmacro %}
<ul>
{% for comment in comments %}
{{ render_comment(comment) }}
{% endfor %}
</ul>
重复使用宏,可以将其保存在单独的文件中
{% import 'macros.html' as macros %}
<ul>
{% for comment in comments %}
{{ macros.render_comment(comment) }}
{% endfor %}
</ul>
继承,先创建名为base.html的模板
<html>
<head>
{% block head %}
<title>{% block title %}{% endblock %} - MyApplication</title>
{% endblock %}
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>
block标签定义的元素可在衍生模板中修改
{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
{{ super() }}
<style>
</style>
{% endblock %}
{% block body %}
<h1>Hello, World</h1>
{% endblock %}
使用super()获取原来模板中的内容
0x2 Flask-Bootstrap & 错误页面
2.1 Flask-Bootstrap
git checkout 3b
Bootstrap官方文档 http://getbootstrap.com/
(venv) $ pip install flask-bootstrap
初始化Flask-Bootstrap
from flask.ext.bootstrap import Bootstrap
#...
bootstrap = Bootstrap(app)
templates/user.html 使用Flask-Bootstrap的模板
{% 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-
collap se">
<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">
<div class="page-header">
<h1>Hello, {{ name }}!</h1>
</div>
</div>
{% endblock %}
如果程序需要向已经有内容的块中添加新内容,必须使用Jinja2提供的super()函数
如果要在衍生模板中添加新的js文件
{% block scripts %}
{{ super() }}
<script type="text/javascript" src="my-script.js"></script>
{% endblock %}
2.2 错误页面
git checkout 3c
@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/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 %}
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 %}
0x3 链接 & 静态文件 & Flask-Moment
3.1 链接
git checkout 3d
Flask提供了url_for()可以使用程序URL映射中保存的信息生成URL
使用url_for()生成动态地址时,将动态部分作为关键字参数传入
url_for('user',name='john',_external=True)的返回结果是http://localhost:5000/user/john
传入url_for()的关键字参数能将任何额外参数添加到查询字符串中
url_for('index',page=2)的返回结果是/?page=2
3.2 静态文件
调用url_for('user',name='john',_external=True)的返回结果是http://xx/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 %}
3.3 Flask-Moment本地化日期和时间
git checkout 3e
学习moment.js提供的全部格式化选项:http://momentjs.com/docs/#/displaying
(venv) $ pip install flask-moment
初始化Flask-moment
from flask.ext.moment import Moment
moment = Moment(app)
templates/base.html:引入moment.js库
{% block scripts %}
{{ super() }}
{{ moment.include_moment() }}
{% endblock %}
代码把变量current_time传入模板进行渲染
from datetime import datetime
@app.route('/')
def index():
return render_template('index.html',current_time=datetime.utcnow())
模板中渲染current_time
templates/index.html:使用Flask-Moment渲染时间戳
<p>The local date and time is {{ moment(current_time).format('LLL') }}.</p>
<p>That was {{ moment(current_time).fromNow(refresh=True) }}.</p>
format('LLL')根据客户端电脑中的时区和时域设置渲染日期时间,L到LLLL对应不同复杂度
format() 还可以接受自定义格式说明符
fromNow()渲染相对应时间戳,指定refresh后,其内容随时间推移而更新
语言可在模板中选择,把语言代码传给lang()
{{ moment.lang('es') }}