视图函数只负责业务逻辑和数据处理(业务逻辑方面)
而模板则取到视图函数的数据结果进行展示(视图展示方面)
代码结构清晰,耦合度低
Jinja2:是 Python 下一个被广泛应用的模板引擎,是由Python实现的模板语言,他的设计思想来源于 Django 的模板引擎,并扩展了其语法和一系列强大的功能,其是Flask内置的模板语言。
模板语言:是一种被设计来自动生成文档的简单文本格式,在模板语言中,一般都会把一些变量传给模板,替换模板的特定位置上预先定义好的占位变量名。
使用render_template函数封装模板引擎
模板的使用
获取变量值:
<h1>整数:{ {number} }h1>
<h1>元祖:{ {tuple[0]} }h1>
<h1>列表:{ { list[0] } }h1>
<h1>字典:{ { dict['key'] } }h1>
分支语句if
变量 |
描述 |
loop.index |
当前迭代的索引(从1开始) |
loop.index0 |
当前迭代的索引(从0开始) |
loop.first |
是否是第一次迭代,返回True/False |
loop.last |
是否是最后一次迭代,返回True/False |
loop.length |
序列的长度 |
{ % if 条件 % }
语句1
{ % else % }
语句2
{ % endif % }
for循环
{% for 变量 in 容器 %}
语句
{% endfor%}
注释
{# 注释内容 #}
使用函数: render_template('模板文件名',key=value)
传递给html文件{{number}}中的number就是key的值。
app = Flask(__name__) #默认省略了三个参数,static_url_path, static_folder, template_folders
static_url_path:静态文件的地址前缀,写成什么,访问静态文件时,就要在前面加上这
static_folder:静态文件所在文件的名字,默认是static,可以不用填
template_folder:模板所在文件夹的名字
response = render_template("file01moban.html")
渲染:通过render_teplate将这个模板html文件给渲染。
自带过滤器:
过滤器的本质就是函数。
* 使用格式:{{ 字符串 | 字符串过滤器 }}
{{ 'hello' | safe }}
{{ 'hello' | capitalize }}
{{ 'HELLO' | lower }}
{{ 'hello' | upper }}
{{ 'hello' | title }}
{{ 'olleh' | reverse }}
{{ '%s is %d' | format('name',17) }}
{{ 'hello' | striptags }}
列表
* 使用格式:{{ 列表 | 列表过滤器 }}
{{ [1,2,3,4,5,6] | first }}
{{ [1,2,3,4,5,6] | last }}
{{ [1,2,3,4,5,6] | length }}
{{ [1,2,3,4,5,6] | sum }}
{{ [6,2,3,1,5,4] | sort }}
语句块操作
{% filter upper %}
#一大堆文字#
{% endfilter %}
链式调用
{{ "hello world" | reverse | upper }}
自定过滤器两种方式:
1.先定义函数,后添加到过滤器列表中
def my_filter():
pass
app.add_template_filter(函数名,过滤器名称)
2.定义函数的同时,就是用过滤器列表装饰
@app.template_filter(过滤器名称)
def my_filter():
pass
在模板中,可能会遇到以下情况:
多个模板具有完全相同的顶部和底部内容
多个模板中具有相同的模板代码内容,但是内容中部分值不一样
多个模板中具有完全相同的 html 代码块内容
像遇到这种情况,可以使用 JinJa2 模板中的 宏、继承、包含来进行实现
宏
{# 定义宏 #}
{% macro input(宏的名称)(name) %}
{{ name }}
荒于嬉
行成于思毁于随
{% endmacro %}
{# 调用宏 #}
{{ input相当于调用input("业精于勤"(传入的name参数)) }}
{# 使用其他文件宏 #}
{% import 'file07macro.html' as other %}
{{ other.input("用户名","123456") }}
继承
模板继承: 使用的关键字是extends
格式: {% extends '父模板文件'%}
注意点:
1.继承一般顶格写,继承父类后子类内容无效
2.使用的全部都是父类内容
3.父类中编写,所有子类共性内容
4.父类中需要留出'坑'(block),供子类去填充特有内容
5.重写了父类模板内容之后,需要保留父类内容,使用super()
模板包含: 使用关键字include
格式: {% include '文件' ignore missing%}
ignore missing: 如果包含的文件不存在不会报错
特点: 没有办法扩展内容,所以不够灵活
父类的内容(在父类的正文内容里填充内容是不会显示的,需要在block之前写内容)
{# 1.正文,留出位置,让不同的子类去填充 #}
父类的标题
{% block contentBlock %}
{% endblock %}
{# 2.底部,留出位置,填写部分内容 #}
{% block bottomBlock %}
{% endblock %}
子类的内容(不需要再设置html创建的相关属性)
{% extends 'fu.html' %}
{# 1.填写子类自己的正文内容 #}
{% block contentBlock %}
每当我错过一个女孩,我就向山上方块砖,于是....就有了长城
{% endblock %}
{# 2.重写,底部内容 #}
{% block bottomBlock %}
{# 保留父类bottom里面的内容 #}
{{ super() }}
{% endblock %}
包含
{% include 'file09zi.html' ignore missing %}
特殊变量
config对象: {{ config }}
request对象method: {{ request.method }}
request对象url: {{ request.url }}
url_for(): {{ url_for('hello_world') }}
(返回的是路由路径)
py服务器程序中:@app.route('/test/
url_for(): {{ url_for('test',token=10) }}
get_flashed_messages():
消耗消息队列数据,指的是通过flash方法存进去的数据。
注意点:
内部的存储依赖于了session,所以需要设置SECRET_KEY
每次获取都会消耗掉队列中的数据。
视图函数中:flash(‘内容’)
{%for message in get_flashed_messages()%}
{{message}}
{%endfor%}
服务器程序
app.config["SECRET_KEY"] = "fjdkfjkdjfkd"
@app.route('/')
def hello_world():
flash("登陆成功")
return render_template("file12flashed.html")
@app.route('/test')
def test():
flash("登陆失败")
return "test...."
html文件程序
{% for message in get_flashed_messages() %}
{{ message }}
{% endfor %}
csrf:跨站请求伪造
用户未登出情况下访问第三方网站,网站盗用了身份获取cookie信息然后伪装成用户发送恶意请求。
防止CSRF攻击
在后端响应cookie设置csrf_token的值,在form表单添加一个隐藏的字段值也是csrf_token,用户点击提交的时候讲这两个值就进行对比如果一样就代表是正常的请求。(cookie和csrf_token拦截器的值和服务器设置的相等)