FLASK学习杂记(三)Flask模板
...
FLASK学习杂记(三)Flask模板
一、Flask模板使用
函数返回一段前端代码,会被flask自动解析,在前端中展示。
@app.route('/index')
def index():
return '<h6>请输入:</h6><input name="inp">'
但直接返回html代码,不利于前后端分离,flask为此提供了Jinja2模板引擎,可以通过render_template()方法渲染模板,再返回给前端。
1.render_template()
写一个简单的html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h6>请输入:</h6>
<input name="inp">
</body>
</html>
用render_template()渲染,flask会在templates文件夹内找到要渲染的html文件。
from flask import render_template
@app.route('/')
def hello_world():
return render_template('index.html')
2.静态文件
在前端开发过程中,也需要css、js 静态文件,flask提供了一个static的文件夹,用于存储相关静态文件。
在static问价夹下新建一个css文件夹用于存储css文件,同理也可在此新建一个js文件夹,用于存储js文件。
这里可以用到url_for()来获取文件地址
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
<link rel="stylesheet" href="{{ url_for('static',filename='css/index.css') }}">
</head>
<body>
<h6>请输入:</h6>
<input name="inp">
</body>
</html>
css修改h6标签颜色
h6{
color: aquamarine;
}
如果想修改静态文件默认位置,可以在flask初始化时候设置static_folder
from flask import Flask
app = Flask(__name__,static_folder='staticfiles')
3.修改模板位置
如果想要自定义模板存放位置,可以在初始化flask的时候,设置template_folder
from flask import Flask
app = Flask(__name__,template_folder='./static/templates')
二、模板传参
render_template(template_name_or_list,**context) 中第一个参数为要渲染的模板或带有模板名称的迭代器,但指挥渲染第一个,第二个参数即为要传给前端的参数。
1.关键字传参
@app.route('/')
def hello_world():
return render_template('index.html',username='Tom',password='123456')
对于username等,前端可以通过{{ username }}的形式直接使用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h1>{{ username }}</h1>
<h2>{{ password }}</h2>
</body>
</html>
2.封装字典传参
@app.route('/')
def hello_world():
dic = {
'username':'Tony',
'password':'123456z'
}
return render_template('index.html',dic = dic)
将所有要穿的参数封装成一个字典传dic给前端,前端可以通过{{dic.username}}或{{dic[‘username’]}}的形式取到
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h1>{{ dic.username }}</h1>
<h2>{{ dic['password'] }}</h2>
</body>
</html>
3.**字典传参
首先将所有变量封装成字典,然后通过**传递。
@app.route('/')
def hello_world():
context = {
'username':'Tony',
'password':'123456z',
'score':{
'Chinese':89,
'math':96,
'PE':70
}
}
return render_template('index.html',**context)
与封装成字典传参不同的是,**context传参前端可以直接通过所需参数名获取
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h1>{{ username }}</h1>
<h2>{{ password }}</h2>
<h3>{{ score.Chinese }}</h3>
<h3>{{ score.math }}</h3>
<h3>{{ score['PE'] }}</h3>
</body>
</html>
4.列表、元组、字典取用
@app.route('/')
def hello_world():
dic = {
'username':'Tony',
'password':'123456z'
}
li = ['Jack','Tom']
tup =(1,3,5)
return render_template('index.html',li = li,tup=tup,dic = dic)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h1>{{ li.0 }}</h1>
<h1>{{ li[1] }}</h1>
<h2>{{ tup.0 }}</h2>
<h2>{{ tup[2] }}</h2>
<h3>{{ dic.username }}</h3>
<h3>{{ dic['password'] }}</h3>
</body>
</html>
三、模板基础
Flask采用Jinja2模板引擎,Jinja模板语法受Django和Python启发,有Python和Django基础更容易理解。
1.Jinja分隔符配置
- {% … %}用于声明,如:{% for i in sep -%}
- {{ … }} 用于打印,如:{{ i }}
- {# … #} 用于注释,类似<!-- 这是注释 -->
- # … ## 行语句
@app.route('/')
def hello_world():
li = ['Jack','Tom','Kitty']
return render_template('index.html',li = li)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h1>
{% for item in li%}
{# 这里是注释的内容 #}
{{ item }}
{% endfor %}
</h1>
</body>
</html>
2.模板过滤器
内置过滤器
abs绝对值
@app.route('/')
def hello_world():
li = [1,-2,3,-4]
return render_template('index.html',li = li)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h2>
{% for item in li %}
{{ item|abs }}
{% endfor %}
</h2>
</body>
</html>
capitalize首字母大写
@app.route('/')
def hello_world():
li = ['tom','kitty','sindy','jack']
return render_template('index.html',li = li)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h2>
{% for item in li %}
{{ item|capitalize }}
{% endfor %}
</h2>
</body>
</html>
default
如果传入的变量为空,会打印定义好的文字,如果不为空要打印变量,需要设置boolean=true。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h2>
{{ is_null|default('this varity is not defined') }}
<br>
{{ "--"|default('this varity is not defined',boolean=true) }}
</h2>
</body>
</html>
dictsirt字典排序
dictsort可以按键或值对字典进行排序,用关键字by来控制,用reverse=true来控制升序,默认false,降序。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h2>
原数据:
<br>
{{ mydict }}
<br>
按键排序:
<br>
{% for item in mydict|dictsort(by ='key') %}
{{ item }}
{% endfor %}
<br>
按值排序 降序:
<br>
{% for item in mydict|dictsort(by ='value') %}
{{ item }}
{% endfor %}
<br>
按值排序 升序:
<br>
{% for item in mydict|dictsort(by ='value',reverse=true) %}
{{ item }}
{% endfor %}
<br>
{{ mydict }}
</h2>
</body>
</html>
可以看到dictsort排序不会对原数据进行修改。
escape转义
在字符串中,如果存在&,<,>等,需要转义成普通字符,才能避免被渲染成html元素,然在flask中会自动将这些字符转义成普通字符。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h3>
{{ '<h1>你好!; 北京。</h1>' }}
</h3>
<h2>
{{ '<h1>你好!; 北京。</h1>'|e }}
</h2>
<h1>
{{ '<h1>你好!; 北京。</h1>'|escape }}
</h1>
</body>
</html>
first、last、length
first返回元素第一项目,last返回最后一个元素,length返回元素长度
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h3>
{{ 'hello'|first }}
</h3>
<h2>
{{ 'hello'|last }}
</h2>
<h1>
{{ 'hello'|length }}
</h1>
</body>
</html>
join
将序列中的元素串联成字符串,默认串联符为空格。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h3>
{{ [1,2,3,4,5]|join }}
</h3>
<h2>
{{ [1,2,3,4,5]|join(',') }}
</h2>
<h1>
{{ [1,2,3,4,5]|join('->') }}
</h1>
</body>
</html>
replace
替换元素中字符为另一个字符
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h3>
{{ 'everyday,everynight'|replace('every','no') }}
</h3>
</body>
</html>
其他过滤器
其他过滤器在此不做详细阐述,可以参考jinja官网上内置过滤器列表查看所有jinja过滤器。
自定义过滤器
通过装饰器template_filter()可以在后端自定义过滤器。
@app.template_filter('my_replace')
def rep(value):
return value.replace('.','!')
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h3>
{{ 'everyday,everynight.' }}
</h3>
<h3>
{{ 'everyday,everynight.'|my_replace }}
</h3>
</body>
</html>
3.结构控制
结构控制包括for循环、if/elif/else条件语句、宏以及块,用{% …%}来控制,每个控制语句要有对应的{% end… %}来结束。
for循环
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h3>
{% for item in ['Tom','Jack','Tony'] %}
{{ item }}
{% endfor %}
</h3>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h3>
{% for item in [] %}
{{ item }}
{% else %}
did not iterate
{% endfor %}
</h3>
</body>
</html>
如上,用{% endfor %} 来结束循环。
for-loop特殊变量访问
loop.index
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h3>
{% for item in ['Tom','Jack','Tony'] %}
{# 从1开始的迭代 #}
{{ loop.index }}:{{ item }}
<br>
{% endfor %}
</h3>
</body>
</html>
loop.index0
<h3>
{% for item in ['Tom','Jack','Tony'] %}
{# 从0开始的迭代 #}
{{ loop.index0 }}:{{ item }}
<br>
{% endfor %}
</h3>
loop.revindex
<h3>
{% for item in ['Tom','Jack','Tony'] %}
{# 从item.length到1的迭代 #}
{{ loop.revindex }}:{{ item }}
<br>
{% endfor %}
</h3>
loop.revindex0
<h3>
{% for item in ['Tom','Jack','Tony'] %}
{# 从item.length-1到0的迭代 #}
{{ loop.revindex0 }}:{{ item }}
<br>
{% endfor %}
</h3>
loop.first
<h3>
{% for item in ['Tom','Jack','Tony'] %}
{# 是否为第一次迭代,返回布尔值 #}
{{ loop.first }}:{{ item }}
<br>
{% endfor %}
</h3>
loop.last
<h3>
{% for item in ['Tom','Jack','Tony'] %}
{# 是否为最后一次迭代,返回布尔值 #}
{{ loop.last }}:{{ item }}
<br>
{% endfor %}
</h3>
loop.length
<h3>
{% for item in ['Tom','Jack','Tony'] %}
{# 返回元素数目 #}
{{ loop.length }}:{{ item }}
<br>
{% endfor %}
</h3>
loop.cycle
<h3>
{% for item in ['Tom','Jack','Tony'] %}
{# 在指定元素中循环产生索引 #}
{{ loop.cycle('a','b') }}:{{ item }}
{{ loop.cycle('a','b','c','d') }}:{{ item }}
<br>
{% endfor %}
</h3>
loop.depth、loop.depth0
<h3>
{% for item in ['Tom','Jack','Tony'] %}
{# 迭代深度,从1开始 #}
{{ loop.depth }}:{{ item }}
<br>
{# 迭代深度,从0开始 #}
{{ loop.depth0 }}:{{ item }}
<br>
{% endfor %}
</h3>
loop.previtem
<h3>
{% for item in ['Tom','Jack','Tony'] %}
{# 查看元素的前一个元素 #}
{{ loop.previtem }}:{{ item }}
<br>
{% endfor %}
</h3>
loop.nextitem
<h3>
{% for item in ['Tom','Jack','Tony'] %}
{# 查看元素的后一个元素 #}
{{ loop.nextitem }}:{{ item }}
<br>
{% endfor %}
</h3>
条件语句
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<h3>
{% for item in ['about','boy','kill'] %}
{{ item }}
{% if item|first =='a' %}
该字母以a开头
{% elif item|first == 'b' %}
该字母以b开头
{% else %}
该字母不以a、b开头
{% endif %}
<br>
{% endfor %}
</h3>
</body>
</html>
宏
可以将宏理解为函数,复用功能,以避免代码重复,可以传参但没有返回值。
用{% macro name(parameter1,parameter2,…) %}的形式来定义宏,parameter为参数,可以设置默认值。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
{% macro input(name,value='',type='text',size=20) %}
<input type="{{ type }}" name="{{ name }}",value="{{ value|e }}",size="{{ size }}">
{% endmacro %}
<p>用户名:{{ input('username') }}</p>
<p>密 码:{{ input('password',type='password') }}</p>
<p>{{ input('提交',type='submit') }}</p>
</body>
</html>
import宏
在世纪开发中,会把宏放入一个单独的html文件中,在使用的时候需要导入
macro.html文件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>macro</title>
</head>
<body>
{% macro input(name,value='',type='text',size=20) %}
<input type="{{ type }}" name="{{ name }}",value="{{ value|e }}",size="{{ size }}">
{% endmacro %}
</body>
</html>
index.html
import
{% import 'macro.html' as marco %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<p>用户名:{{ marco.input('username') }}</p>
<p>密 码:{{ marco.input('password',type='password') }}</p>
<p>{{ marco.input('提交',type='submit') }}</p>
</body>
</html>
from … import …
{% from 'macro.html' import input %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>index</title>
</head>
<body>
<p>用户名:{{ input('username') }}</p>
<p>密 码:{{ input('password',type='password') }}</p>
<p>{{ input('提交',type='submit') }}</p>
</body>
</html>
块和模板继承
块的存在为jinjia模板继承提供了很大的便利,用{% block name %}来定义,每个块结束都由对应的{% endblock %} 来控制,也可用{% endblock name %} 来结束以增加可读性。
*{
margin: 0;
padding: 0;
}
.bg{
width: 1500px;
height: 50px;
background-color: #e7b434;
}
#top{
background-color: antiquewhite;
}
#footer{
background-color: #6d6a6a;
}
父模板
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>
{% block title%}
base
{% endblock %}
</title>
<link rel="stylesheet" href="{{ url_for('static',filename='css/base.css') }}">
</head>
<body>
<div id="top" class="bg">
</div>
<div class="bg">
{% block center %}
<h1>这里是要被继承的父模块</h1>
{% endblock %}
</div>
<div id="footer" class="bg"></div>
</body>
</html>
@app.route('/block/')
def block():
return render_template('base.html')
子模块
{% extends 'base.html' %}
{% block title %}
extend
{% endblock %}
{% block center %}
<h2>这是继承了父模板的子模板</h2>
{% endblock %}
@app.route('/extendblock/')
def extendblock():
return render_template('extend.html')
可以看到子模块中只需要修改被block包裹的部分即可。
用super()调用父块结果:
{% extends 'base.html' %}
{% block title %}
extend
{% endblock %}
{% block center %}
<h2>这是继承了父模板的子模板</h2>
{{ super() }}
{% endblock %}
可以看到父块的结果被返回。
嵌套扩展
@app.route('/parent/')
def parent():
return render_template('parent.html')
@app.route('/child/')
def child():
return render_template('child.html')
@app.route('/grandchild/')
def grandchild():
return render_template('grandchild.html')
parent
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>
{% block title %}
Parent
{% endblock %}
</title>
</head>
<body>
body: {% block body %}This is from parent.{% endblock %}
</body>
</html>
child
{% extends 'parent.html' %}
{% block title %}Child
{% endblock%}
{% block body %} This is Child. {{ super() }}
{% endblock %}
grandchild
{% extends 'child.html' %}
{% block title %} Grandchild{% endblock %}
{% block body %}This is grandchild.
{{ super.super() }}
{% endblock %}
parent
child
grandchild
用super.super()可以引用parent。
set
可以理解成定义变量并赋值,有作用域限制,在块内设置的变量无法现实在块外,循环中设置的也无法显示在循环外。如下,在循环内外set一个相同的item,
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>set</title>
</head>
<body>
{% set item = 0 %}
{% for i in [1,2,3] %}
i = {{ i }}
{% set item = i %}
item = {{ item }}
<br>
{% endfor %}
{% if item == 0%} item {% endif %}
</body>
</html>
如果想实现跨作用域传播,可以通过namespace的方法。
如下,通过namespace() set n.flage = false,n.s=1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>set</title>
</head>
<body>
{% set n = namespace(flage=false,s=1) %}
{% for item in [1,2,3,4] %}
{{ item }}
{% if item > 3%}
{% set n.flage = true %}
{% set n.s = item %}
{% endif %}
<br>
{% endfor %}
n.flage:{{ n.flage }},n.s:{{ n.s }}
</body>
</html>
4.Jinjia表达式
Jinjia表达式与python非常相似,有python基础的更好理解,这里只稍微列举,详细请见Jinjia官网
- 元组:(’a’,‘b’,‘c’);
- 列表:[1,2,3] ;
- 字典:{“user”:“Tom”,“password”:123456}
- 数学运算 : +(加)、-(减)、*(乘)、%(除)、**(幂)…
- 比较:== 、!=、>、<、<=、>=
- 逻辑:and 、 or 、not 、expr
- 其他:in 、is…
本文地址:https://blog.****.net/m0_46221758/article/details/112309593
下一篇: 使用IE浏览器查看页面手机端效果的方法