Flask 基础组件(四):模板
1、模板的使用
1.1 语法
1.1.1 流程控制
逻辑语法
Jinja2模板语言中的 for
{% for foo in g %} {% endfor %}
Jinja2模板语言中的 if
{% if g %} {% elif g %} {% else %} {% endif %}
1.1.2 变量#
{{}} 1.2 实例 数据准备 后端定义几个字符串,用于传递到前端 STUDENT = {‘name‘: ‘Old‘, ‘age‘: 38, ‘gender‘: ‘中‘}, STUDENT_LIST = [ {‘name‘: ‘Old‘, ‘age‘: 38, ‘gender‘: ‘中‘}, {‘name‘: ‘Boy‘, ‘age‘: 73, ‘gender‘: ‘男‘}, {‘name‘: ‘EDU‘, ‘age‘: 84, ‘gender‘: ‘女‘} ] STUDENT_DICT = { 1: {‘name‘: ‘Old‘, ‘age‘: 38, ‘gender‘: ‘中‘}, 2: {‘name‘: ‘Boy‘, ‘age‘: 73, ‘gender‘: ‘男‘}, 3: {‘name‘: ‘EDU‘, ‘age‘: 84, ‘gender‘: ‘女‘}, }
1.2.1. 使用STUDENT字典传递至前端#
前端页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <table border="1px"> <thead> <tr> <th>姓名</th> <th>年龄</th> <th>性别</th> </tr> </thead> <tbody> {% for foo in stu %} <tr> <td>{{ foo.name }}</td> <td>{{ foo.age }}</td> <td>{{ foo.gender }}</td> </tr> {% endfor %} </tbody> </table> </body> </html>
后端代码
from flask import Flask,render_template,request app = Flask(__name__) STUDENT = {‘name‘: ‘Old‘, ‘age‘: 38, ‘gender‘: ‘中‘}, @app.route(‘/login‘,methods=["POST","GET"]) def login(): if request.method == "GET": return render_template("login.html",stu=STUDENT) if __name__ == ‘__main__‘: app.run("0.0.0.0", 9876)
1.2.2. STUDENT_LIST 列表传入前端Jinja2 模板的操作
前端页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <table border="1px"> <thead> <tr> <th>姓名</th> <th>年龄</th> <th>性别</th> </tr> </thead> <tbody> {% for foo in stu %} <tr> <td>{{ foo.get("name") }}</td> <td>{{ foo.age }}</td> <td>{{ foo["gender"] }}</td> </tr> {% endfor %} </tbody> </table> </body> </html>
上面我们用了三种取值方式,这里foo就是每个字典
后端代码
from flask import Flask,render_template,request app = Flask(__name__) STUDENT_LIST = [ {‘name‘: ‘Old‘, ‘age‘: 38, ‘gender‘: ‘中‘}, {‘name‘: ‘Boy‘, ‘age‘: 73, ‘gender‘: ‘男‘}, {‘name‘: ‘EDU‘, ‘age‘: 84, ‘gender‘: ‘女‘} ] @app.route(‘/login‘,methods=["POST","GET"]) def login(): if request.method == "GET": return render_template("login.html",stu=STUDENT_LIST) if __name__ == ‘__main__‘: app.run("0.0.0.0", 9876)
1.2.3 STUDENT_DICT 大字典传入前端 Jinja2 模板#
前端页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <table border="1px"> <thead> <tr> <th>序号</th> <th>姓名</th> <th>年龄</th> <th>性别</th> </tr> </thead> <tbody> {% for foo in stu %} <tr> <td>{{ foo }}</td> <td>{{ stu.get(foo).name }}</td> <td>{{ stu.get(foo).age }}</td> <td>{{ stu.get(foo).gender }}</td> </tr> {% endfor %} </tbody> </table> </body> </html>
后端代码
from flask import Flask,render_template,request app = Flask(__name__) STUDENT_DICT = { 1: {‘name‘: ‘Old‘, ‘age‘: 38, ‘gender‘: ‘中‘}, 2: {‘name‘: ‘Boy‘, ‘age‘: 73, ‘gender‘: ‘男‘}, 3: {‘name‘: ‘EDU‘, ‘age‘: 84, ‘gender‘: ‘女‘}, } @app.route(‘/login‘,methods=["POST","GET"]) def login(): if request.method == "GET": return render_template("login.html",stu=STUDENT_DICT) if __name__ == ‘__main__‘: app.run("0.0.0.0", 9876)
在遍历字典的时候,foo 其实是相当于拿出了字典中的Key
1.2.4 Markup#
该方法和django中的safe一样都是防止xss攻击、
from flask import Flask,render_template,request from markupsafe import Markup app = Flask(__name__) @app.route(‘/login‘,methods=["POST","GET"]) def login(): if request.method == "GET": my_in = Markup("<input type=‘text‘ name=‘uname‘>") return render_template("login.html",ss=my_in) if __name__ == ‘__main__‘: app.run("0.0.0.0", 9876)
前端页面生成的标签:
<input type="text" name="uname"> 1.4 模板继承 模板继承语法: 使用‘extend’语句,来指明继承的父模板。 示例代码: {% extends ‘base.html‘ %}
block语法:
一般在父模版中,定义一些公共的代码。子模版可能要根据具体的需求实现不同的代码。
这时候父模版就应该提供一个接口,让父模版来实现。从而实现具体业务需求的功能。
在父模版中:
{% block block的名字 %} {% endblock %}
在子模版中:
{% extends ‘base.html‘ %} {% block body_block %} 子模板代码 {% endblock %}
调用父模版的代码block中的代码:
默认情况下,子模版如果实现了父模版定义的block,那么子模版block中的代码就会覆盖掉父模版中的代码,如果想在子模版中仍然保持父模版代码,需要用super() 函数调用。具体代码如下:
{% block body_block %} {{ super() }} {#super()调用父模版代码#} <p style="background-color: green;">首页子模板代码</p> {% endblock %}
调用另一个block中的代码:
一个模板中使用其他模板的代码。那么可以通过‘{{ self.其他block名字() }}‘
示例代码如下:
{% block another_block %} 我是另一个模板的代码 {% endblock %} {% block body_block %} {{ self.another_block() }} <p style="background-color: green;">首页子模板代码</p> {% endblock %}
其他注意事项:
子模版中的代码,第一行应该是继承的代码。‘extends‘.
子模版中,如果要实现自己的代码,应该放到block中,如果放到外面,将无法被渲染。
2、自定义模板方法
Flask中自定义模板方法的方式和Bottle相似,创建一个函数并通过参数的形式传入render_template,如:
#login.html <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <h1>自定义函数</h1> {{ww()|safe}} </body> </html> html
# run.py #!/usr/bin/env python # -*- coding:utf-8 -*- from flask import Flask,render_template app = Flask(__name__) def wupeiqi(): return ‘<h1>Wupeiqi</h1>‘ @app.route(‘/login‘, methods=[‘GET‘, ‘POST‘]) def login(): return render_template(‘login.html‘, ww=wupeiqi) app.run()
其他
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% macro input(name, type=‘text‘, value=‘‘) %} <input type="{{ type }}" name="{{ name }}" value="{{ value }}"> {% endmacro %} {{ input(‘n1‘) }} {% include ‘tp.html‘ %} <h1>asdf{{ v.k1}}</h1> </body> </html>
3 过滤器
使用方式: 变量名|过滤器
{{variable | filter_name(*args)}}
如果没有任何参数传给过滤器,则可以把括号省略掉
在 jinja2 中,过滤器是可以支持链式调用的,
示例如下{{ "hello world" | reverse | upper }}
flask自带的过滤器
字符串操作
禁用转义: {{ ‘<em>hello</em>‘ | safe }}
删除标签: {{ ‘<em>hello</em>‘ | striptags }}
首字母大写: {{ ‘hello‘ | capitalize }}
所有值小写: {{ ‘HELLO‘ | lower }}
首字母大写: {{ ‘hello world‘ | title }}
字符串反转: {{ ‘hello‘ | reverse }}
字符串截断: {{ ‘hello world‘ | truncate(5) }}
列表操作
获取列表长度: {{ [1,2,3,4,5,6] | length }}
列表求和: {{ [1,2,3,4,5,6] | sum }}
列表排序: {{ [6,2,3,1,5,4] | sort }}
自定义过滤器
方式一:
通过Flask应用对象的add_template_filter方法
def list_reverse(li): temp = list(li) temp.reverse() return temp # 可以给过滤器器一个名字,如果没有,默认就是函数的名字 app.add_template_filter(list_reverse,‘li_reverse‘)
通过装饰器来实现自定义过滤器
# 使用装饰器事项过滤器, # 如果不传入参数,默认过滤器名字就是函数的名字 @app.template_filter() def my_filter(args): temp = list(args) temp.reverse() return temp
在html模板中调用过滤器:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>jinjia2模板测试</title> </head> <body> <h1>len: {{ [1,2,3,4,5,6] | length }}</h1> #此处调用上文flask自带的过滤器 <h1> {{ [1,2,3,4,5,6] | my_filter }}</h1> #此处调用上文自定义过滤器 </body> </html>
xss,csrf,json 攻击
https://www.cnblogs.com/shengulong/p/7693107.html
{{variable | filter_name(*args)}} 如果没有任何参数传给过滤器,则可以把括号省略掉 在 jinja2 中,过滤器是可以支持链式调用的,示例如下 {{ "hello world" | reverse | upper }}
作者:Gavininn
链接:https://www.jianshu.com/p/1ae7d2c3c223
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。