day3
模板
jinja2简介
使用模板的好处:
- 视图函数只负责业务逻辑和数据处理(业务逻辑方面)
- 而模板则取到视图函数的数据结果进行展示(视图展示方面)
- 代码结构清晰,耦合度低
模板的使用
1.在项目下创建 template 文件夹,用于储存模板文件,并创建html文件。(可以设置文件夹属性,以便在代码中有智能提示,设置html中的模板语言为jinja2,以便智能提示)
2.创建视图函数,将该模板内容进行渲染
app.route('/')
def index():
return render_template(模板名字)
3.传入参数到模板中
app.route('/')
def index():
return render_template(模板名字,
指定的名字(my_list)=参数名字)
模板中代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
我的模板html内容
<br/>{{ 指定的名字(my_list) }}
</body>
</html>
模板中可以进行运算
过滤器
过滤器的本质就是函数。在模板中不能直接调用python中的某些方法,那么就用到过滤器。
过滤器的使用方式
变量名 | 过滤器
{{ my_list | lengh}}
safe (安全) 禁用转义
<p>{{"HELLO" | safe}}</p>
escape
链式调用
{{ “hello” | reverse | upper }}
带参数的过滤器
{{ xxx | sum(aa) }}
常用内建过滤器
字符串操作
safe: 禁用转义
capitalize:把变量值的首字母转成大写,其余字母转小写
lower: 把值转换为小写
upper: 把值转换为大写
title: 把值中每个单词首字母大写
reverse: 字符串反转
format: 格式化输出
striptags: 渲染之前把值中所有的HTML标签都删掉
truncate: 字符串截断 <p>{{ 'hello every one' | truncate(9)}}</p>
列表操作
first: 取第一个元素
last: 取最后一个元素
length: 获取列表长度
sum: 列表求和
sort: 列表排序
自定义过滤器
方式1:装饰器形式
装饰器传入的参数是自定义过滤器的名称。
@app.tamplate_filter(lireverse)
def do_listreverse(li):
temp_li = list(li)
temp_li.reverse()
return temp_li
方式2:app.add_template_filter(function,过滤器名字)
def do_listreverse(li):
temp_li = list(li)
temp_li.reverse()
return temp_li
app.add_template_filter(do_listreverse,'lireverse')
在HTML中使用
{{ my_array | lireverse }}
控制代码块
判断和循环
if语句
{%if 条件 %}
执行的内容
{%elif 条件 %}
执行的内容
{% else %}
执行的内容
{% endif %}
循环
{% for post in posts %}
执行的内容
{% endfor %}
在一个for循环中可以访问这些特殊变量
loop.index | 当前循环迭代的次数(从 1 开始) |
---|---|
loop.index0 | 当前循环迭代的次数(从 0 开始) |
loop.revindex | 到循环结束需要迭代的次数(从 1 开始) |
loop.revindex0 | 到循环结束需要迭代的次数(从 0 开始) |
loop.first | 如果是第一次迭代,为 True 。 |
loop.last | 如果是最后一次迭代,为 True 。 |
loop.length | 序列中的项目数。 |
loop.cycle | 在一串序列间期取值的辅助函数。见下面示例程序。 |
模板代码的复用
宏
把重复出现的代码定义为宏,达到可以多次调用的效果。和封装一个函数类似。
# 定义宏 {{% macro 相当于函数名(参数) %}}
{{% macro input11(type,value,size) %}}
<input type="{{ type }}" name="username" value="{{ value }}" size="{{ size }}">
{% endmacro %}
# 调用宏
{{ input11('type','value','50')}}
继承
去异存同,把相同的代码块放入父类。不同的用
{% block script %}
{% endblock %}
base.html
{% block top %}
顶部菜单
{% endblock top %}
{% block content %}
{% endblock content %}
{% block bottom %}
底部
{% endblock bottom %}
index.html
{% extends 'base.html' %}
{% block content %}
需要填充的内容
{% endblock content %}
包含
包含只能包含不变的内容
- include 的使用加上关键字ignore missing
{% include 'hello.html' ignore missing %}
特有的变量和函数
可以在模板中直接取到的变量
配置 config
request
session
g 变量
两个直接可以使用的函数
{{ url_for }}
闪现消息 {{% for foo in get_flashed_message %}}
WTF表单
使用 Flask-WTF 实现表单
- 配置参数,关闭 CSRF 校验
app.config['WTF_CSRF_ENABLED'] = False
CSRF:跨站请求伪造,后续会讲到
模板页面:
<form method="post">
{{ form.username.label }} {{ form.username }}<br/>
{{ form.password.label }} {{ form.password }}<br/>
{{ form.password2.label }} {{ form.password2 }}<br/>
{{ form.submit }}
</form>
视图函数:
from flask import Flask,render_template, flash
#导入wtf扩展的表单类
from flask_wtf import FlaskForm
#导入自定义表单需要的字段
from wtforms import SubmitField,StringField,PasswordField
#导入wtf扩展提供的表单验证器
from wtforms.validators import DataRequired,EqualTo
app = Flask(__name__)
app.config['SECRET_KEY']='SECRET_KEY'
#自定义表单类,文本字段、密码字段、提交按钮
class RegisterForm(FlaskForm):
username = StringField("用户名:", validators=[DataRequired("请输入用户名")], render_kw={"placeholder": "请输入用户名"})
password = PasswordField("密码:", validators=[DataRequired("请输入密码")])
password2 = PasswordField("确认密码:", validators=[DataRequired("请输入确认密码"), EqualTo("password", "两次密码不一致")])
submit = SubmitField("注册")
#定义根路由视图函数,生成表单对象,获取表单数据,进行表单数据验证
@app.route('/demo2', methods=["get", "post"])
def demo2():
register_form = RegisterForm()
# 验证表单
if register_form.validate_on_submit():
# 如果代码能走到这个地方,那么就代码表单中所有的数据都能验证成功
username = request.form.get("username")
password = request.form.get("password")
password2 = request.form.get("password2")
# 假装做注册操作
print(username, password, password2)
return "success"
else:
if request.method == "POST":
flash("参数有误或者不完整")
return render_template('temp_register.html', form=register_form)
if __name__ == '__main__':
app.run(debug=True)