flask模板
# 基本使用
user = {
'username': 'Grey Li',
'bio': 'A boy who loves movies and music.',
}
movies = [
{'name': 'My Neighbor Totoro', 'year': '1988'},
{'name': 'Three Colours trilogy', 'year': '1993'},
{'name': 'Forrest Gump', 'year': '1994'},
{'name': 'Perfect Blue', 'year': '1997'},
{'name': 'The Matrix', 'year': '1999'},
{'name': 'Memento', 'year': '2000'},
{'name': 'The Bucket list', 'year': '2007'},
{'name': 'Black Swan', 'year': '2010'},
{'name': 'Gone Girl', 'year': '2014'},
{'name': 'CoCo', 'year': '2017'},
]
@app.route('/watchlist')
def watchlist():
return render_template('watchlist.html', user=user, movies=movies)
@app.route('/')
def index():
return render_template('index.html')
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{{ user.username }}'s Watchlist</title>
</head>
<body>
<a href="{{ url_for('index') }}">← Return</a>
<h2>{{ user.username }}</h2>
{% if user.bio %}
<i>{{ user.bio }}</i>
{% else %}
<i>This user has not provided a bio.</i>
{% endif %}
{# 下面是电影清单(这是注释) #}
<h5>{{ user.username }}'s Watchlist ({{ movies|length }}):</h5>
<ul>
{% for movie in movies %}
<li>{{ movie.name }} - {{ movie.year }}</li>
{% endfor %}
</ul>
</body>
</html>
<!--
{% if user.bio %}
<i>{{ user.bio }}</i>
{% else %}
<i>This user has not provided a bio.</i>
{% endif %}
-->
<!-- 使用变量 `user` 下`username` 字段 -->
{{ user.username }}
<!-- 循环 -->
{% for movie in movies %}
{% endfor %}
<!-- 注释 -->
{# ... #}
<!-- if else -->
{% if user.bio %}
{% else %}
{% endif %}
使用 flask
提供的渲染函数 render_template('xx.html',user = user, movies = movies)
,渲染后结果返回。
# 上下文
# 渲染时传入变量
render_template('xx.html',user = user, movies = movies)
# 在模板中定义变量
{% set navigation = [('/', 'Home'), ('/about', 'About')] %}
# 内置上下文变量
config
, request
, session
, g
# 自定义上下文
# 注册模板上下文处理函数
@app.context_processor
def inject_foo():
foo = 'I am foo.'
return dict(foo=foo) # 等同于return {'foo': foo}
<li>Filter: {{ foo|musical }}</li>
# 全局函数
jinja
, 常用的, range
,lipsum
, dict(**items)
flask
url_for
, get_flashed_messages
# 自定义全局函数
@app.template_global()
def bar():
return 'I am bar.'
# 模板使用
# <li>Global: {{ bar() }}</li>
# 过滤器
{{ movies|length }}
<!-- 相当于 -->
len(movies)
jinja filter 过滤器 (opens new window)
# 自定义过滤器
from flask import Markup
@app.template_filter()
def musical(s):
return s + Markup(' ♫')
# 模板使用
# <li>Filter: {{ 'test'|musical }}</li>
# 'test' + ' ♫'
# Test
在 Jinja2
中,测试器(Test)是一些用来测试变量或表达式,返回布尔值(True或False)的特殊函数
{% set name='baz' %}
<li>Test: {% if name is baz %}I am baz.{% endif %}</li>
jinja test 测试器 (opens new window)
# 自定义测试
@app.template_test()
def baz(n):
if n == 'baz':
return True
return False
# <li>Test: {% if name is baz %}I am baz.{% endif %}</li>
# https://docs.jinkan.org/docs/jinja2/api.html#writing-tests
@app.template_test()
def baz(n):
if n == 'baz':
return True
return False
# 模板环境对象
模板环境中的全局函数、过滤器和测试器分别存储在Environment对象的 globals
、filters
和 tests
属性中
这三个属性都是字典对象。
# 自定义全局对象
def bar():
return 'I am bar.'
foo = 'I am foo.'
app.jinja_env.globals['bar'] = bar
app.jinja_env.globals['foo'] = foo
# 自定义过滤器
def smiling(s):
return s + ' :)'
app.jinja_env.filters['smiling'] = smiling
# 自定义测试器
def baz(n):
if n == 'baz':
return True
return False
app.jinja_env.tests['baz'] = baz
# 模板结构组织
# 局部模板
当多个独立模板中都会使用同一块HTML代码时,我们可以把这部分代码抽离出来,存储到局部模板中。
{%include'_banner.html'%}
# 宏
<!-- macros.html -->
{% macro qux(amount=1) %}
{% if amount == 1 %}
I am qux.
{% elif amount > 1 %}
We are quxs.
{% endif %}
{% endmacro %}
<!-- index.html -->
{% from 'macros.html' import qux %}
...
{{ qux(amount=5) }}
# 模板继承
<!-- 基模板 -->
<!DOCTYPE html>
<html>
<head>
<!-- header 块 -->
{% block head %}
<meta charset="utf-8">
<!-- title 快 -->
<title>{% block title %}Template - HelloFlask{% endblock %}</title>
<link rel="icon" type="image/x-icon" href="{{ url_for('static', filename='favicon.ico') }}">
<!-- styles 快 -->
{% block styles %}
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css' ) }}">
{% endblock %}
{% endblock %}
</head>
<body>
<nav>
<ul><li><a href="{{ url_for('index') }}">Home</a></li></ul>
</nav>
<main>
{% for message in get_flashed_messages() %}
<div class="alert">{{ message }}</div>
{% endfor %}
<!-- content 块 -->
{% block content %}{% endblock %}
</main>
<footer>
<!-- footer 快 -->
{% block footer %}
<small> © 2018 <a href="http://greyli.com" title="Written by Grey Li">Grey Li</a> /
<a href="https://github.com/greyli/helloflask" title="Fork me on GitHub">GitHub</a> /
<a href="http://helloflask.com" title="A HelloFlask project">HelloFlask</a>
</small>
{% endblock %}
</footer>
<!-- script 块 -->
{% block scripts %}{% endblock %}
</body>
</html>
- 定义了 6 个代码块
<!-- 继承 基模板 -->
{% extends 'base.html' %}
{% from 'macros.html' import qux %}
<!-- 覆盖 content 块 -->
{% block content %}
{% set name='baz' %}
<h1>Template</h1>
<ul>
<li><a href="{{ url_for('watchlist') }}">Watchlist</a></li>
<li>Filter: {{ foo|musical }}</li>
<li>Global: {{ bar() }}</li>
<li>Test: {% if name is baz %}I am baz.{% endif %}</li>
<li>Macro: {{ qux(amount=5) }}</li>
</ul>
{% endblock %}
# 覆盖块
<!-- 覆盖 title 块 -->
<title>{{ user.username }}'s Watchlist</title>
# 追加内容
{% block styles %}
{{ super() }}
<style>
.foo {
color: red;
}
</style>
{% endblock %}
# 404
from flask import Flask, render_template
...
@app.errorhandler(404)
def page_not_found(e):
return render_template('errors/404.html'), 404