模板文件就是按照特定规则书写的一个负责展示效果的html文件;模板引擎就是提供了特定规则的解释和替换的功能。为了简化这种重复工作,通常我们会为项目定制一个基础模板。
在Flask中使用的就是该模板引擎,由Flask核心开发组人员开发。
1.准备工作,目录结构
project/
manage.py # 项目的启动控制文件
templates/ # 所有的模板文件
2.渲染模板文件
在templates下创建一个模板文件(hello.html),内容如下:
渲染字符串
模板渲染
@app.route('/')
def index():
# return '模板引擎测试'
# 渲染模板文件
# return render_template('hello.html')
# 渲染字符串
return render_template_string('渲染字符串')
3.使用变量
在templates下创建一个模板文件(hello.html),内容如下:
Nice,{{ g.name }}
模板渲染
@app.route('/var/')
def va():
# g对象,在模板使用中不需要分配
g.name = 'Nian'
# return render_template('hello.html', name='dandan')
# return render_template_string('{{ name }}', name='dandan')
return render_template_string('{{ g.name }}')
4.使用函数
在模板文件中可以使用特定的函数,对指定的变量处理后再显示,用法如下:
Nice,{{ g.name | upper }}
常用函数
5.流程控制
分支语句(if-else)
{% if name %}{{ name }}{% else %}Stranger{% endif %}
@app.route('/control/')
def control():
# return render_template('if-else.html', name = 'Nian')
return render_template('if-else.html')
循环语句
{% for i in range(1, 5) %}{{ i }}{% endfor %}
6.文件包含
include1.html
# include.htmlInclude 1{% include 'include2.html' %}
# include2.html
被包含include 2
7.宏的使用
{# 定义宏 #}
{% macro show_name(name) %}Hello, {{ name }}{% endmacro %}
{# 调用宏 #}
{{ show_name(name) }}
# 宏的使用
@app.route('/macro/')
def macro():
# return render_template('macro.html', name = 'Nian')
return render_template('macro2.html', name = 'dandan')
说明:
采用类似Python中的函数的形式进行定义和调用,可以把特定功能的内容定义为一个宏,哪里使用哪里调用即可。
8.模板继承
# parents.html
{% block title %}父级标题{% endblock %}{% block body %}
默认内容
{% endblock %}# children.html
{% extends 'parents.html ' %}
{% block title %}
丹丹测试
{% endblock %}
{% block body %}
这是模板继承 这是=》{{ super() }}
{% endblock %}
1.安装
pip install flask-bootstrap
2.使用:
from flask_bootstrap import Bootstrap
# 创建实例
app = Flask(__name__)
bootstrap = Bootstrap(app)
3.测试模板文件boot.html
{# 继承自bootstrap模板 #}
{% extends 'bootstrap/base.html' %}
{% block title %}
用户注册
{% endblock %}
{% block content %}欢迎丹丹来注册{% endblock %}
4.bootstrap继承模板base.html中定义的block
使用bootstrap时,发现重写block后原来的显示效果消失,可能是忘了调用super
1.说明:
一个项目中,很多页面都很相似,只有细微的差别,如果每个页面都定制,势必会有大量的重复代码。为了简化这种重复工作,通常我们会为项目定制一个基础模板,让它继承自bootstrap,其他页面继承自该基础模板,只需稍微定制即可。
2.步骤
1.从bootcss.com复制一个导航条
2.将container-fluid改为container
3.根据需要,定制显示内容
3.基础模板文件base.html
{% extends 'bootstrap/base.html' %}
{% block title %}
丹丹的标题
{% endblock %}
{% block navbar %}Toggle navigation 首页Link (current)LinkDropdown ActionAnother actionSomething else hereSeparated linkOne more separated linkSubmitLinkDropdown ActionAnother actionSomething else hereSeparated link{% endblock %}
{# 定制内容 #}
{% block content %}{# 这里可以为弹出内容显示预留位置 #}
{% block page_content %}
默认内容
{% endblock %}{% endblock %}
错误页面定制
1.添加视图函数
# 错误页面定制
@app.errorhandler(404)
def error(e):
return render_template('404.html')
2.定制404.html
{% extends 'base.html' %}
{% block title %}
出错了
{% endblock %}
{% block content %}找不见了吧@_@{% endblock %}
回顾url_for函数
1.根据视图函数名反向构造路由地址,路由需要的直接构造,多出来的参数以GET方式 传递
2.若需要构造完整的外部链接,需要添加_extenal=True参数
3.通常网站中的点击链接都是url_for构造的
注册
加载静态资源
1.flask框架中静态资源的默认目录为static,项目目录如下:
project/
manage.py # 启动控制文件
static/ # 存放静态资源
templates/ # 存放模板文件
2.加载网站图标
{# 加载收藏夹的图标 #}
{% block head %}
{{ super }}{% endblock %}
3.静态资源加载
# manage.py
# 加载静态文件
@app.route('/source/')
def source():
return render_template('static.html')
# static.html
{% block styles %}
{{ super() }}{% endblock %}
4.设置本地日期和时间
# base.html
{#引入moment.js类#}
{% block scripts %}
{{ super() }}
{{ moment.include_moment() }}
{% endblock %}
# manage.py
# 使用Flask-Monment本地化日期和时间
from datetime import datetime
@app.route('/testtime/')
def testtime():
return render_template('testtime.html', current_time = datetime.utcnow())
# testtime.html
{% block content %}The local date and time is {{ moment(current_time).format('LLL') }}{% endblock %}
5.表单
# maange.py
from flask import Flask, render_template, session, redirect, url_for
from flask_script import Manager
from flask_bootstrap import Bootstrap
from wtforms import SubmitField, StringField, IntegerField
from wtforms.validators import Required
from flask_wtf import Form
# 实例化对象
app = Flask(__name__)
bootstrap = Bootstrap(app)
manager = Manager(app)
app.config['SECRET_KEY'] = 'idandan'
class PersonInfo(Form):
name = StringField('Name: ', validators=[Required()])
age = IntegerField('age: ', validators=[Required()])
submit = SubmitField('Submit')
@app.route('/', methods=['GET', 'POST'])
def index():
name = None
age = None
form = PersonInfo()
if form.validate_on_submit():
session['name'] = form.name.data
session['age'] = form.age.data
return redirect(url_for('index'))
# name = form.name.data
# age = form.age.data
# form.name.data = ''
# form.age.data = '' # ? 不能清空数据???
# return render_template('personInfo.html', form = form, name = session.get('name'), age = session.get('age'))
return render_template('personInfo.html', form = form)
if __name__ == '__main__':
manager.run()
# personInfo.html
{% import 'bootstrap/wtf.html' as wtf %}
{% block title %}
Form
{% endblock %}
{% block content %}
{##}
{# Nice,#}
{# {% if name %}#}
{# {{ name }}, your age is {{ age }}?#}
{# {% else %}#}
{# Stranger!#}
{# {% endif %}#}
{##}Nice,
{% if session.get('name') %}
{{ session.get('name') }}, your age is {{ session.get('age') }}?
{% else %}
Stranger!
{% endif %}{{ wtf.quick_form(form) }}
{% endblock %}