文章目录
- 一、模板结构组织
- 1.1 局部模板
- 1.2 宏
- 1.3 模板继承
- 二、模板进阶
- 2.1 空白控制
- 2.2 加载静态文件
- 2.3 消息闪现
- 2.4 自定义错误页面
- 2.5 在js和css中使用Jinja2
一、模板结构组织
1.1 局部模板
当多个独立模板中都会使用同一块HTML代码时,我们可以把这部分代码抽离出来,存储到局部模板中。这样,既可以避免重复,也可以方便统一管理。
{% include '_banner.html' %} # 为了和普通模板分开,局部模板的命名通常都以一个下划线开始
1.2 宏
宏是Jinja2提供的一个非常有用的特性,它类似Python的函数。使用宏可以把一部分代码封装到宏里,通过传递的参数来构建内容,最后渲染。
_macros.html
# 在创建宏时,使用macro与endmaccro标签来声明宏。
{ % macro qux(amount) = 1 %}{% if amount == 1 %}I am a boy.{% elif amount >1 %}I am a girl.{% endif %}
{%% endmacro %}
使用时,像Python中导入函数一样导入。
{% from '_macros.html' import qux %}
....
{{qux(amount=5)}}
另外在使用宏的时候要注意上下文问题。出于性能的考虑,并且为了让这一切保持显式,默认情况下include一个模板时会传递上下文到局部模板中,但import不会。所以我们需要导入时显式的使用with context来声明传入当前模板的上下文。
1.3 模板继承
Jinja2允许你定义一个基本模板,把网页上的导航栏、页脚等通用内容放在基模板中,而每一个继承模板的子模板都会在渲染时自动包含这些部分。
基模板 base.html
<!DOCTYPE html>
<html>
<head>{% block head %}<meta charset="utf-8"><title>{% block title %} 基模板 {% endblock %}</title>{% block style %}{% endblock %}{% endblock %}
</head>
<body><header><!-- 网站头部内容 --></header><nav><!-- 网站导航栏内容 --></nav><main><!-- 网站主要内容 -->{% block content %}{% endblock %}</main><footer><!-- 网站页脚内容 -->{% block footer %}...{% endblock %}</footer>{% block scripts %}{% endblock %}
</body>
</html>
基本模板中块的开始和技术分别使用block和endblock标签俩声明,并且块与块之间可以嵌套。我们只需要在子模板中定义同名的快来执行继承操作。
子模板 index.html
{% extends 'base.html' %}
{from 'macros.html' import qux %}{% block content %}
{% set name = 'baz' %}
<h1>sdad</h1>
<li>macro:{{ qux{amount=5) )} </li>
{% endblock %}
在子模块中,可以对父模块中的块执行两种操作:
- 覆盖内容:创建同名模块即可。
- 追加内容:需要使用super()函数进行声明。
# 追加内容至base.html 的styles模块
{% block styles %}
{{ super() }}
<style>.foo{color: #FFF;}
</style>
{% endblock %}
二、模板进阶
2.1 空白控制
- 如果想在渲染时去掉模板中的空行,可以在定界符内添加减号。
<div>
{% if True -%}<p>Hello!</p>
{%- endif %}
- 还有一种办法是使用模板环境对象提供的trin_blocks和lstrip_blocks属性设置,欠着删除Jinja2语句的第一个空行,后者删除Jinja2语句所在行之前的空格和tabs
app.jinja_env.trin_blocks = True
app.jinja_enc.lstrip_blocks = True
需要注意的是宏内的空白控制行为只能用第一种办法设置。
2.2 加载静态文件
- 添加Favicon
<link rel="icon" type="image/x-icon" href="{{ url_for('static', filename='favicon.ico') }}" >
- 使用css框架
{% block styles %}<link rel="stylesheet" href="{{ url_for('static', filename='css/bootstrap.min.css') }}" >
{% endblock %}{% block scripts %}<script src="{{ url_for('static', filename='js/jquery.min.js') }}"></script>
{% endblock %}
- 使用宏加载静态资源
<--定义宏-->
{% macro static_file(type, url, loacl=True) %}{% if local %}{% set url=url_for('static', filename=url) %}{% endif %}{% if type == 'css' %}<link rel="stylesheet" href="{{ url }}">{% elif type == 'js' %}<script src="{{ url }}"></script>{% endif %}
{% endmacro %}<--使用宏-->
{% import "static.macros.html" as static %}{{ static.static_file("css", "/static/css/style.css") }}
{{ static.static_file("js", "/static/js/script.js") }}
2.3 消息闪现
flask提供了一个非常有用的flash()函数,它可以用来闪现需要显示给用户的消息。
# 使用flash“闪现”消息
@app.route('/login', methods=['GET', 'POST'])
def login():if request.method == 'POST':username = request.form['username']password = request.form['password']# 模拟用户登录验证if username == 'admin' and password == 'password':flash('登录成功!', 'success')return redirect(url_for('index'))else:flash('用户名或密码错误!', 'error')return render_template('login.html')# 模板渲染flash消息
{% with messages = get_flashed_messages() %}{% if messages %}<ul class="messages">{% for message in messages %}<li class="{{ message[1] }}">{{ message[0] }}</li>{% endfor %}</ul>{% endif %}
{% endwith %}
2.4 自定义错误页面
flask提供了@app.errorhandler()
装饰器来自定义错误页面。它接收三个参数,code:状态码,name:原因短语,description:错误描述。
@app.errorhandler(404)
def page_not_found(e):return render_template('error/404.html'), 404
2.5 在js和css中使用Jinja2
- 嵌入/行内式js/css
难以维护,跳过。 - 定义为js/css变量
// script.js
var name = '{{ name }}';
console.log('Hello ' + name + '!');/* style.css */
:root {--background-color: {{ bg_color }};--color: {{ text_color }};
}#foo {color: var(--color);background-color: var(--background-color);
}
当然还有很多其他办法。