模板基本语法
{% if user %} {{ user }} {% else %} hello! <ul> {% for index in indexs %} <li> {{ index }} </li> {% endfor %} </ul>
一 变量
在模板中{{ variable }}结构表示变量,是一种特殊的占位符,告诉模板引擎这个位置的值,从渲染模板时使用的数据中获取;Jinja2除了能识别基本类型的变量,还能识别{};
视图:
from flask import Flask, render_template app = Flask(__name__) @app.route("/index") def index(): data = { "name": "test", "size": 11, "adict": {"title": "index"}, "alist": [1,2,3,4,5,6] } return render_template('index.html', **data) # return render_template("index.html", name="tile") if __name__ == '__main__': app.run() View Code模板:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta http-equiv='Content-type' content='text/htm'> </head> <body> <p>name---{{ name }}</p> <p>size---{{ size }}</p> <p>adict---title:{{ adict["title"] }}</p> <p>adict---title:{{ adict.title }}</p> <p>alist---{{ alist }}</p> <p>alist---:alist[0]:{{ alist[0] }}</p> <p>alist---:alist[2]:{{ alist.2 }}</p> <p>alist---:alist[0]+alist[1]:{{ alist[0] + alist[1] }}</p> <p>{{ "hello" + "flask" }}</p> </body> </html> View Code自定义错误页面:
@app.errorhandler(404) def page_not_found(e): return render_template('404.html'), 404 View Code
二 过滤器
过滤器的本质就是函数。有时候我们不仅仅只是需要输出变量的值,我们还需要修改变量的显示,甚至格式化、运算等等,这就用到了过滤器。 过滤器的使用方式为:变量名 | 过滤器。 过滤器名写在变量名后面,中间用 | 分隔。如:{{variable | capitalize}},这个过滤器的作用:把变量variable的值的首字母转换为大写,其他字母转换为小写。 其他常用过滤器如下:
2.1 字符串过滤器:
safe:禁用转义; <p>{{ '<em>hello</em>' | safe }}</p> capitalize:把变量值的首字母转成大写,其余字母转小写; <p>{{ 'hello' | capitalize }}</p> lower:把值转成小写; <p>{{ 'HELLO' | lower }}</p> upper:把值转成大写; <p>{{ 'hello' | upper }}</p> title:把值中的每个单词的首字母都转成大写; <p>{{ 'hello' | title }}</p> trim:把值的首尾空格去掉; <p>{{ ' hello world ' | trim }}</p> reverse:字符串反转; <p>{{ 'olleh' | reverse }}</p> format:格式化输出; <p>{{ '%s is %d' | format('name',17) }}</p> striptags:渲染之前把值中所有的HTML标签都删掉; <p>{{ '<em>hello</em>' | striptags }}</p>2.2 支持链式使用过滤器
<p>{{ “ hello world “ | trim | upper }}</p>2.3 列表过滤器
first:取第一个元素 <p>{{ [1,2,3,4,5,6] | first }}</p> last:取最后一个元素 <p>{{ [1,2,3,4,5,6] | last }}</p> length:获取列表长度 <p>{{ [1,2,3,4,5,6] | length }}</p> sum:列表求和 <p>{{ [1,2,3,4,5,6] | sum }}</p> sort:列表排序 <p>{{ [6,2,3,1,5,4] | sort }}</p>2.4 语句块过滤
{% filter upper %} this is a Flask Jinja2 introduction {% endfilter %}2.5 自定义过滤器:
过滤器的本质是函数。当模板内置的过滤器不能满足需求,可以自定义过滤器。自定义过滤器有两种实现方式:一种是通过Flask应用对象的add_template_filter方法。还可以通过装饰器来实现自定义过滤器。
自定义的过滤器名称如果和内置的过滤器重名,会覆盖内置的过滤器。
实现方式一:通过调用应用程序实例的add_template_filter方法实现自定义过滤器。该方法第一个参数是函数名,第二个参数是自定义的过滤器名称。
def list_step_2(li): """自定义过滤器""" return li[::2] # 注册过滤器 app.add_template_filter(list_step_2, "li2") View Code实现方式二:用装饰器来实现自定义过滤器。装饰器传入的参数是自定义的过滤器名称。
@app.template_filter("li3") def list_step_3(li): """自定义过滤器""" return li[::3] View Code
三 Web表单:
web表单是web应用程序的基本功能。
它是HTML页面中负责数据采集的部件。表单有三个部分组成:表单标签、表单域、表单按钮。表单允许用户输入数据,负责HTML页面数据采集,通过表单将用户输入的数据提交给服务器。
在Flask中,为了处理web表单,我们一般使用Flask-WTF扩展,它封装了WTForms,并且它有验证表单数据的功能。
WTForms支持的HTML标准字段
字段对象说明StringField文本字段TextAreaField多行文本字段PasswordField密码文本字段HiddenField隐藏文本字段DateField文本字段,值为datetime.date格式DateTimeField文本字段,值为datetime.datetime格式IntegerField文本字段,值为整数DecimalField文本字段,值为decimal.DecimalFloatField文本字段,值为浮点数BooleanField复选框,值为True和FalseRadioField一组单选框SelectField下拉列表SelectMultipleField下拉列表,可选择多个值FileField文本上传字段SubmitField表单提交按钮FormField把表单作为字段嵌入另一个表单FieldList一组指定类型的字段
WTForms常用验证函数
验证函数说明DataRequired确保字段中有数据EqualTo比较两个字段的值,常用于比较两次密码输入Length验证输入的字符串长度NumberRange验证输入的值在数字范围内URL验证URLAnyOf验证输入值在可选列表中NoneOf验证输入值不在可选列表中
使用Flask-WTF需要配置参数SECRET_KEY。
CSRF_ENABLED是为了CSRF(跨站请求伪造)保护。 SECRET_KEY用来生成加密令牌,当CSRF激活的时候,该设置会根据设置的密匙生成加密令牌。
在HTML页面中直接写form表单:
#模板文件 <form method='post'> <input type="text" name="username" placeholder='Username'> <input type="password" name="password" placeholder='password'> <input type="submit"> </form> View Code视图函数中获取表单数据:
from flask import Flask,render_template,request @app.route('/login',methods=['GET','POST']) def login(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] print username,password return render_template('login.html',method=request.method) View Code
使用Flask-WTF实现表单。
pip install Flask-WTF配置参数:
app.config['SECRET_KEY'] = '.........'模板页面:
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta http-equiv='Content-type' content='text/htm'> </head> <body> <form method="post"> {{ reg_form.csrf_token }} {{ reg_form.username.label }} <p>{{ reg_form.username }}</p> {{ reg_form.username.errors.0 }} {{ reg_form.password.label }} <p>{{ reg_form.password }}</p> {{ reg_form.password.errors.0 }} {{ reg_form.repassword.label }} <p>{{ reg_form.repassword }}</p> {{ reg_form.repassword.errors.0 }} <br> {{ reg_form.submit }} </form> </body> </html> View Code视图函数:
from flask import Flask, render_template, url_for, redirect, session from flask_wtf import FlaskForm from wtforms import StringField, PasswordField, SubmitField from wtforms.validators import DataRequired, EqualTo app = Flask(__name__) app.config["SECRET_KEY"] = "ada898u2q11joloadad02" class RegiterForm(FlaskForm): username = StringField(label="用户名", validators=[DataRequired("用户名不能为空")]) password = PasswordField(label="密码", validators=[DataRequired("密码不能为空")]) repassword = PasswordField(label="确认密码", validators=[DataRequired("确认密码不能为空"), EqualTo("password", "两次密码输入不一致")]) submit = SubmitField(label="提交") @app.route("/register", methods=['GET', "POST"]) def register(): # 创建表单对象, 如果是post请求, 前端发送了数据,flask会把数据在构造form对象的数据,存在对象中 reg_form = RegiterForm() # 判断form中的数据是否合法 if reg_form.validate_on_submit(): username = reg_form.username.data password = reg_form.password.data repassword = reg_form.repassword.data session["username"] = username print(username, password, repassword) return redirect(url_for("index")) return render_template('register.html', reg_form=reg_form) @app.route("/index") def index(): username = session.get("username") return "hello %s " % username if __name__ == '__main__': app.run() View Code
四 控制语句
4.1 if控制语句
@app.route('/user') def user(): user = 'wusong' return render_template('user.html',user=user) View Code <html> <head> {% if user %} <title> hello {{user}} </title> {% else %} <title> welcome to flask </title> {% endif %} </head> <body> <h1>hello world</h1> </body> </html> View Code
4.2 for循环语句
@app.route('/loop') def loop(): fruit = ['apple','orange','pear','grape'] return render_template('loop.html',fruit=fruit) View Code <html> <head> {% if user %} <title> hello {{user}} </title> {% else %} <title> welcome to flask </title> {% endif %} </head> <body> <h1>hello world</h1> <ul> {% for index in fruit %} <li>{{ index }}</li> {% endfor %} </ul> </body> </html> View Code
五 宏、继承、包含
类似于python中的函数,宏的作用就是在模板中重复利用代码,避免代码冗余。
Jinja2支持宏,还可以导入宏,需要在多处重复使用的模板代码片段可以写入单独的文件,再包含在所有模板中,以避免重复。
5.1 宏
定义宏
{% macro input() %} <input type="text" name="username" value=""> {% endmacro %}调用宏
{{ input() }}定义带参数的宏
{% macro input1(name, value="", type="text") %} <input type="{{ type }}" name="{{ name }}" value="{{ value }}"> {% endmacro %}调用宏,并传递参数
{{ input1(pwd, type="password") }}把宏单独抽取出来,封装成html文件,其它模板中导入使用
文件名可以自定义macro_input.html
{% macro function() %} <input type="text" name="username" placeholde="Username"> <input type="password" name="password" placeholde="Password"> <input type="submit"> {% endmacro %}在其它模板文件中先导入,再调用
{% import 'macro_input.html' as func %} {{ func.function() }}
5.2模板继承
模板继承是为了重用模板中的公共内容。一般Web开发中,继承主要使用在网站的顶部菜单、底部。这些内容可以定义在父模板中,子模板直接继承,而不需要重复书写。
{% block top %}.......{% endblock %}标签定义的内容,相当于在父模板中挖个坑,当子模板继承父模板时,可以进行填充。
父模板:base.html
{% block top %} 顶部菜单 {% endblock top %} {% block content %} {% endblock content %} {% block bottom %} 底部 {% endblock bottom %}子模板:
{% extends 'base.html' %} {% block content %} 需要填充的内容 {% endblock content %}模板继承使用时注意点:
不支持多继承。
为了便于阅读,在子模板中使用extends时,尽量写在模板的第一行。
不能在一个模板文件中定义多个相同名字的block标签。
当在页面中使用多个block标签时,建议给结束标签起个名字,当多个block嵌套时,阅读性更好。
5.3包含(Include)
Jinja2模板中,除了宏和继承,还支持一种代码重用的功能,叫包含(Include)。它的功能是将另一个模板整个加载到当前模板中,并直接渲染。
示例:
include的使用
{% include 'hello.html' %}包含在使用时,如果包含的模板文件不存在时,程序会抛出TemplateNotFound异常,可以加上ignore missing关键字。如果包含的模板文件不存在,会忽略这条include语句。
示例:
include的使用加上关键字ignore missing
{% include 'hello.html' ignore missing %} 宏、继承、包含:宏(Macro)、继承(Block)、包含(include)均能实现代码的复用。
继承(Block)的本质是代码替换,一般用来实现多个页面中重复不变的区域。
宏(Macro)的功能类似函数,可以传入参数,需要定义、调用。
包含(include)是直接将目标模板文件整个渲染出来。
六 Flask中的特殊变量和方法
在Flask中,有一些特殊的变量和方法是可以在模板文件中直接访问的。
config 对象:
config 对象就是Flask的config对象,也就是 app.config 对象。 {{ config.SQLALCHEMY_DATABASE_URI }}request 对象:
就是 Flask 中表示当前请求的 request 对象,request对象中保存了一次HTTP请求的一切信息。
request常用的属性如下:
属性说明类型data记录请求的数据,并转换为字符串*form记录请求中的表单数据MultiDictargs记录请求中的查询参数MultiDictcookies记录请求中的cookie信息Dictheaders记录请求中的报文头EnvironHeadersmethod记录请求使用的HTTP方法GET/POSTurl记录请求的URL地址stringfiles记录请求上传的文件*{{ request.url }}
url_for 方法:
url_for() 会返回传入的路由函数对应的URL,所谓路由函数就是被 app.route() 路由装饰器装饰的函数。如果我们定义的路由函数是带有参数的,则可以将这些参数作为命名参数传入。
{{ url_for('index') }} {{ url_for('post', post_id=1024) }}get_flashed_messages方法:
返回之前在Flask中通过 flash() 传入的信息列表。把字符串对象表示的消息加入到一个消息队列中,然后通过调用 get_flashed_messages() 方法取出。
{% for message in get_flashed_messages() %} {{ message }} {% endfor %}示例:
from flask import Flask, render_template, flash app = Flask(__name__) app.config["SECRET_KEY"] = "diaj29u912kjwsle01sda" flag = True @app.route("/index") def index(): global flag if flag: flash("flash1") flash("flash2") flash("flash3") flag = False return render_template("index.html") if __name__ == '__main__': app.run() View Code <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>Title</title> <meta http-equiv='Content-type' content='text/htm'> </head> <body> <h1>闪现</h1> {% for msg in get_flashed_messages() %} {{ msg }} {% endfor %} </body> </html> View Code
转载于:https://www.cnblogs.com/ForT/p/10789964.html
相关资源:模特FLASH模板