1. 模板
- 在项目下创建 templates 文件夹,用于存放所有的模板文件
创建视图函数,进行模板渲染
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return 'index'
@app.route('/demo1')
def demo1():
my_int = 10
my_str = "哈哈"
my_list = [1, 4, 7, 9 ,6]
my_dict = {
"id": 1,
"name": "laowang"
}
return render_template('template.html',
my_int=my_int,
my_str=my_str,
my_list=my_list,
my_dict=my_dict
)
if __name__ == '__main__':
app.run(debug=True)
html中模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{ my_str }}<br/>
{{ my_int }}<br/>
{{ my_list }}<br/>
{{ my_dict }}<br/>
取值<br/>
{{ my_dict['name'] }}<br/>
{{ my_dict.id }}<br/>
{{ my_list[0] }}<br/>
{{ my_list.0 }}<br/>
计算<br/>
{{ my_int + my_list.1 }}<br/>
</body>
</html>
运行效果
2. 过滤器
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return 'index'
@app.route('/demo1')
def demo1():
my_int = 10
my_str = "<h1>我是大标题</h1>"
my_list = [1, 4, 7, 9, 6]
my_dict = {
"id": 1,
"name": "laowang"
}
my_dict_list = [
{
"good_name": "大白菜",
"price": 18
},
{
"good_name": "白罗卜",
"price": 10
}
]
return render_template('template.html',
my_int=my_int,
my_str=my_str,
my_list=my_list,
my_dict=my_dict,
my_dict_list=my_dict_list
)
if __name__ == '__main__':
app.run(debug=True)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{ my_str }}<br/>
{{ my_int }}<br/>
{{ my_list }}<br/>
{{ my_dict }}<br/>
取值<br/>
{{ my_dict['name'] }}<br/>
{{ my_dict.id }}<br/>
{{ my_list[0] }}<br/>
{{ my_list.0 }}<br/>
计算<br/>
{{ my_int + my_list.1 }}<br/>
<hr>
{{ 'hello' | upper }}<br/>
{{ 'HELLO' | lower }}<br/>
{{ 'hello' | reverse }}<br/>
{# flask特有的 #}
{{ 'hello' | reverse | upper }}
列表过滤器:<br/>
{{ my_list | last }}<br/>
长度:{{ my_list | length }}<br/>
排序:{{ my_list | sort }}<br/>
<hr>
html的显示<br/>
{{ my_str }}
按html显示 {{ my_str | safe }}
默认html的字符串会按照原样显示,可以使用 safe 进行标识该字符串是安全的
如果使用safe标识该字符串是安全的话,那么就会按照html语言格式进行显示或者执行
<br/>
<hr/>
使用过滤器传参数<br/>
总价: {{ my_dict_list | sum(attribute='price') }}
</body>
</html>
3. 自定义过滤器
当模板内置的过滤器不能满足需求,可以自定义过滤器。自定义过滤器有两种实现方式:
- 一种是通过Flask应用对象的 add_template_filter 方法
- 通过装饰器来实现自定义过滤
重要:自定义的过滤器名称如果和内置的过滤器重名,会覆盖内置的过滤器。
通过调用应用程序实例的 add_template_filter 方法实现自定义过滤器。该方法第一个参数是函数名,第二个参数是自定义的过滤器名称:
def do_listreverse(li):
# 通过原列表创建一个新列表
temp_li = list(li)
# 将新列表进行返转
temp_li.reverse()
return temp_li
app.add_template_filter(do_listreverse,'lireverse')
用装饰器来实现自定义过滤器。装饰器传入的参数是自定义的过滤器名称:
@app.template_filter('lireverse')
def do_listreverse(li):
# 通过原列表创建一个新列表
temp_li = list(li)
# 将新列表进行返转
temp_li.reverse()
return temp_li
4.控制代码块
控制代码块主要包含两个:
- if/else if /else / endif
- for / endfor
*在一个 for 循环块中你可以访问这些特殊的变量:
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def index():
return 'index'
@app.route('/demo1')
def demo1():
# 只显示4行数据,背景颜色依次为:黄,绿,红,紫
my_list = [
{
"id": 1,
"value": "我爱工作"
},
{
"id": 2,
"value": "工作使人快乐"
},
{
"id": 3,
"value": "沉迷于工作无法自拔"
},
{
"id": 4,
"value": "日渐消瘦"
},
{
"id": 5,
"value": "以梦为马,越骑越傻"
}
]
return render_template('control.html', my_list=my_list)
if __name__ == '__main__':
app.run(debug=True)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% for item in my_list if item.id != 5 %}
{% if loop.index == 1 %}
<li style="background-color: orange">{{ item.value }}</li>
{% elif loop.index == 2 %}
<li style="background-color: green">{{ item.value }}</li>
{% elif loop.index == 3 %}
<li style="background-color: red">{{ item.value }}</li>
{% else %}
<li style="background-color: purple">{{ item.value }}</li>
{% endif %}
{% endfor %}
</body>
</html>
5. 宏
对宏(macro)的理解:
- 把它看作 Jinja2 中的一个函数,它会返回一个模板或者 HTML 字符串
- 为了避免反复地编写同样的模板代码,出现代码冗余,可以把他们写成函数以进行重用
- 需要在多处重复使用的模板代码片段可以写入单独的文件,再包含在所有模板中,以避免重复
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
宏
<form>
<label>用户名:</label><input type="text" name="username"><br/>
<label>身份证号:</label><input type="text" name="idcard"><br/>
<label>密码:</label><input type="password" name="password"><br/>
<label>确认密码:</label><input type="password" name="password2"><br/>
<input type="submit" value="注册">
</form>
<hr>
使用宏实现
{% macro input(label="", type="text", name="", value="") %}
<label>{{ label }}</label><input type="{{ type }}" name="{{ name }}" value="{{ value }}">
{% endmacro %}
<form>
{{ input("用户名:", name="username") }}<br/>
{{ input("身份证号:", name="idcard") }}<br/>
{{ input("密码:", type="password", name="password") }}<br/>
{{ input("确认密码:", type="password", name="password2") }}<br/>
{{ input(type="submit", value="注册") }}
</form>
</body>
</html>
6. 模板继承
模板继承是为了重用模板中的公共内容。
- 标签定义的内容
{% block top %} {% endblock %}
- 相当于在父模板中挖个坑,当子模板继承父模板时,可以进行填充
- 子模板使用 extends 指令声明这个模板继承自哪个模板
- 父模板中定义的块在子模板中被重新定义,在子模板中调用父模板的内容可以使用super()
父模板
- base.html
{% block top %}
顶部菜单
{% endblock top %}
{% block content %}
{% endblock content %}
{% block bottom %}
底部
{% endblock bottom %}
子模板
- extends指令声明这个模板继承自哪
{% extends 'base.html' %}
{% block content %}
需要填充的内容
{% endblock content %}
- 模板继承使用时注意点:
- 不支持多继承
- 在子模板中使用extends时,尽量写在模板的第一行
- 不能在一个模板文件中定义多个相同名字的block标签
- 当在页面中使用多个block标签时,建议给结束标签起个名字,当多个block嵌套时,阅读性更好。
7.包含
将另一个模板整个加载到当前模板中,并直接渲染。
- include的使用
{% include 'hello.html' %}
- include 的使用加上关键字ignore missing
{% include 'hello.html' ignore missing %}
8. 模板中特有的变量和函数
- config
{{config.DEBUG}}
- request
{{request.url}}
- session
{{session.name}}
- g变量
{{ g.name }}
- url_for()
# url_for会根据传入的路由器函数名,返回该路由对应的URL,在模板中始终使用url_for()就可以安全的修改路由绑定的URL,则不比担心模板中渲染出错的链接
{{url_for('index')}}
# /
# 如果我们定义的路由URL是带有参数的,则可以把它们作为关键字参数传入url_for(),Flask会把他们填充进最终生成的URL中:
{{ url_for('post', post_id=1)}}
# /post/1
- get_flashed_messages()
# 这个函数会返回之前在flask中通过flask()传入的消息的列表,flash函数的作用很简单,可以把由Python字符串表示的消息加入一个消息队列中,再使用get_flashed_message()函数取出它们并消费掉:
{%for message in get_flashed_messages()%}
{{message}}
{%endfor%}
9. CSRF(跨站请求伪造)
防止 CSRF 攻击
- 在客户端向后端请求界面数据的时候,后端会往响应中的 cookie 中设置 csrf_token 的值
- 在 Form 表单中添加一个隐藏的的字段,值也是 csrf_token
- 在用户点击提交的时候,会带上这两个值向后台发起请求
- 后端接受到请求,以会以下几件事件:
- 从 cookie中取出 csrf_token
- 从 表单数据中取出来隐藏的 csrf_token 的值
- 进行对比
- 如果比较之后两值一样,那么代表是正常的请求,如果没取到或者比较不一样,代表不是正常的请求,不执行下一步操作
---------------------------------------------------END-----------------------------------------------
---------------------------------------------------END-----------------------------------------------