您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Model Center   Code  
会员   
   
 
     
   
 订阅
  捐助
flask之二
 
   次浏览      
 2019-7-25
 
编辑推荐:
本文来自于segmentfault,文章介绍了使用template渲染模板时,传递关键字参数以及模板中的宏等相关内容。

预热

在渲染模板的时候,默认会从项目根路径下的templates目录下查找模板

如果想要指定模板路径的时候,就在初始化APP的时候,这样操作即可:

app = Flask(__name__,template_folder='C:/templates') #template_folder可以指定模板位置

模板传参

在使用render_template渲染模板的时候,可以传递关键字参数,以后直接在模板中使用就可以了

如果参数过多的话,那么就可以将所有的参数放到一个字典中,然后再传这个参数的时候使用**将字典打散成关键字参数。

小例子:

my_template.py

from flask import Flask,render_template
app = Flask(__name__)
app.debug = True
@app.route('/')
def hello_world():
context = {
'username': 'wanghui',
'age':19,
'children':{
'user':'ccc',
'type':'stu',
}
}
return render_template('index.html', **context)
# return render_template('index.html',context=context)
# return render_template('index.html',username='wanghui',age=19)
if __name__ == '__main__':
app.run()

templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>my blog</title>
</head>
<body>
<h1>这是模板渲染的数据</h1>
{#<p>{{ username }}</p>#}
{#<p>{{ age }}</p>#}
{{ context.username }}
{{ context.age }}
<p>{{ username }}</p>
<p>{{ children.user }}</p>
</body>
</html>

模板中的url_for

模板中的url_for和视图函数中的url_for是类似的,也是传递视图函数的名字,也可以传递参数。使用的时候,需要在url_for两边加上一个{{ url_for('func_name'),ref='/',id='1'}}

templates.py

from flask import Flask,render_template,url_for
app = Flask(__name__)
app.debug = True
@app.route('/')
def hello_world():
return render_template('index.html')
@app.route('/accounts/login/<id>/')
def login(id):
return render_template('login.html')
if __name__ == '__main__':
app.run(port=8888)

templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>my blog</title>
</head>
<body>
<h1>这是从模板中渲染的</h1>
<p><a href="{{ url_for('login',ref='/',id='1') }}">登陆</a></p>
</body>
</html>

templates/login.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login page</title>
</head>
<body>
<h1>这是登录页面</h1>
{#{{ 用来存放变量 }}#}
{#{% 用来执行函数或者逻辑代码 %}#}
</body>
</html>

过滤器

有时候我们需要在模板中对一些变量进行处理,那么就必须要类似于python中的函数一样,可以将这个值传到函数中,然后做一些操作。在模板中过滤器相当于是一个函数,把当前的变量传入到过滤器中,然后过滤器会根据自己的功能,再返回相应的值,之后再将结果渲染到页面上。

基本语法:{{ variable |过滤器的名字 }}

guo

abs(value):返回一个数值的绝对值。 例如:-1|abs。

default(value,default_value,boolean=false):如果当前变量没有值,则会使用参数中的值来代替。name|default('xiaotuo')——如果name不存在,则会使用xiaotuo来替代。boolean=False默认是在只有这个变量为undefined的时候才会使用default中的值,如果想使用python的形式判断是否为false,则可以传递boolean=true。也可以使用or来替换。

escape(value)或e:转义字符,会将<、>等符号转义成HTML中的符号。例如:content|escape或content|e。

first(value):返回一个序列的第一个元素。names|first。

format(value,arags,*kwargs):格式化字符串。例如以下代码:

{{ "%s" - "%s"|format('Hello?',"Foo!") }}\
将输出:Helloo? - Foo!

last(value):返回一个序列的最后一个元素。示例:names|last。

length(value):返回一个序列或者字典的长度。示例:names|length。

join(value,d=u''):将一个序列用d这个参数的值拼接成字符串。

safe(value):如果开启了全局转义,那么safe过滤器会将变量关掉转义。示例:

content_html|safe。

int(value):将值转换为int类型。

float(value):将值转换为float类型。

lower(value):将字符串转换为小写。

upper(value):将字符串转换为小写。

replace(value,old,new): 替换将old替换为new的字符串。

truncate(value,length=255,killwords=False):截取length长度的字符串。

striptags(value):删除字符串中所有的HTML标签,如果出现多个空格,将替换成一个空格。

trim:截取字符串前面和后面的空白字符。

string(value):将变量转换成字符串。

wordcount(s):计算一个长字符串中单词的个数。

default过滤器详解:

如果某个变量使用方式是{{ value|default('默认值')}},如果value这个key不存在的话就使用过滤器提供的默认值;如果类似于python中判断一个值是否为False(例如:空字典,空字符串,空列表的话)那么久必须要传递另外一个参数{{ value | default('默认值',boolean=True)}};

可以使用or来替换default('默认值',boolean=True)(例如{{ siginature or '此人很懒没有留下任何说明'}})

例子:

defaulte_falter.py

from flask import Flask,render_template
app = Flask(__name__)
@app.route('/')
def index():
context = {
'position':-9,
'signature':'',
#'signature':'this ismy blog'
}
return render_template('index.html',**context)
if __name__ == '__main__':
app.run(debug=True)

templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>MyBlog</title>
</head>
<body>
{#<p>个性签名:{{ signature|default('此人很懒没有留下任何说明!',boolean=True) }}</p>#}
<p>个性签名:{{ signature or '此人很懒没有留下任何说明!'}}</p>
</body>
</html>

esacape:转义过滤器

safe过滤器:可以关闭一公分字符串的自动转义

escape过滤器:对某个字符串进行转义

autoescape过滤器:可以对其代码框内的代码块关闭自动转义

first:返回序列中的第一个元素

last:返回序列中的最后一个元素

format:格式化输出

length:长度计算

int:转换成整数

replase:旧字符串换成新的

truncate:指定长度截取(结合striptags去除掉html字段之后截取纯净字符串然后按字数去做预览页填充)

striptags:去除标签中的html字段

worldcount(s):统计一个长字符串中的单词数

小例子:

escape.py

from flask import Flask,render_template
app = Flask(__name__)
@app.route('/')
def hello_world():
context = {
'position':-9,
'signature':'<script>alert("Hello world!")</script>',
'persons':['abc','def'],
'age':"18",
'article':'hello hello xxooo xxooo!!'
}
return render_template('index.html',**context)
if __name__ == '__main__':
app.run(debug=True,port=8080)

templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>MyBlog</title>
</head>
<body>
{#{% autoescape off %}#}
{#<p>个性签名:{{ signature }}</p>#}
{#{% endautoescape %}#}
<p>{{ signature|safe }}</p>
<p>{{ persons|first }}</p>
<p>{{ persons[0] }}</p>
<p>{{ persons|last }}</p>
<p>{{ persons[-1] }}</p>
<p>{{ "我的名字是%s"|format("hello word!") }}</p>
<p>{{ "人数是 %d"|format(persons|length) }}</p>
{% if age|int == 18 %}
<p>年龄是18岁</p>
{% else %}
<p>年龄不是18岁</p>
{% endif %}
<p>{{ article|replace('hello','sssssz') }}</p>
<p>{{ article|truncate(length=5) }}</p>
<p>{{ signature|striptags }}</p>
</body>
</html>

自定义模板过滤器

在python文件中写好自己的过滤器(本质上就是一个函数)

如果要在模板中调用这个过滤器,那就需要在这个函数上加一个装饰器@app.template_filter('过滤器名称')

自动加载的话就在app下添加

app.config['TEMPLATES_AUTO_RELOAD'] = True

小例子:

define_filter.py

from flask import Flask,render_template
app = Flask(__name__)
app.config['TEMPLATES_AUTO_RELOAD'] = True
@app.route('/')
def hello_world():
context={
'article':'anyway hello anyway hello abccc'
}
return render_template('index.html',**context)
@app.template_filter('cut')
def cut(value):
vaule = value.replace("hello","sbsb")
return value
if __name__ == '__main__':
app.run(debug=True,port=9090)**

templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>myblog</title>
</head>
<body>
<p>{{ article|cut }}</p>
</body>
</html>

实战自定义过滤器

时间处理(从现在到发帖的时间差)

shizhan.py

from flask import Flask,render_template
from datetime import datetime
app = Flask(__name__)
app.config['TEMPLATES_AUTO_RELOAD'] = True
@app.route('/')
def index():
context={
'article':'aaa bbb ccc',
'create_time':datetime(2018,02,23,10,12,11)
}
return render_template('index.html',**context)
@app.template_filter('handle_time')
def handle_time(time):
'''
1.距离现在的时间多久,如果间隔在一分钟以内就表示刚刚
2.在一小时以内就显示xx分钟前
3.在24小时以内就显示xx小时前
4. 在一个月之内就显示多少天之前
5. 否则就显示具体的时间
:param time:
:return:
'''
if isinstance(time,datetime):
now = datetime.now()
timestamp = (now - time).total_seconds() #获取间隔秒数
if timestamp < 60:
return "刚刚"
elif timestamp >=60 and timestamp<= 60*60:
minutes = timestamp/60
return "%s分钟前",int(minutes)
elif timestamp >= 60*60 and timestamp <= 60*60*24:
hours = timestamp/(60*60)
return "%s小时前",int(hours)
elif timestamp >= 60*60*24 and timestamp<= 60*60*24*30:
days = timestamp/(60*60*24)
return "%s天前",int(days)
else:
return time.strftime('%Y-%m-%d %H:%M')
if __name__ == '__main__':
app.run(port=9092,debug=True)

 

templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>MyBlog</title>
</head>
<body>
<p>发表时间:{{ create_time|handle_time }}</p>
</body>
</html>

条件判断

For循环

在jinjia2中的for循环,跟python中的for循环基本是一致的,也是用for in形式;

而且可以便利所有的序列以及迭代器,但是唯一不同的是jinjia2中的for循环没有break和continue

小例子:

for_ex.py

from flask import Flask,render_template
app = Flask(__name__)
@app.route('/')
def hello_world():
context = {
'users':['user01','user02','user03'],
'person':{
'username':'wanghui',
'age':21,
'country':'china',
},
'books':[
{
'name':'sk1',
'author':'saa',
'price':100,
},
{
'name': 'aaaeede1',
'author': 'se232aa',
'price': 103,
},
{
'name': 'AAAew',
'author': 'VVVeqwea',
'price': 190,
},
{
'name': 'skfdfds1',
'author': 'sdfsfsdfdaa',
'price': 30,
}
]
}
return render_template('index.html',**context)
if __name__ == '__main__':
app.run(debug=True)

templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>MyBlog</title>
</head>
<body>
<ul>
{% for user in users %}
<p>{{ user }}</p>
{% endfor %}
</ul>
<table>
<thead>
<tr>
<th>用户名</th>
<th>年龄</th>
<th>国家</th>
</tr>
</thead>
<tbody>
<tr>
{% for key,value in person.items() %}
<td>{{ value }}</td>
{% endfor %}
</tr>
</tbody>
<table>
<thead>
<tr>
<th>ID</th>
<th>书名</th>
<th>作者</th>
<th>价格</th>
<th>总数</th>
</tr>
</thead>
<tbody>
{% for book in books %}
{% if loop.first %}
<tr style="background: red">
{% elif loop.last %}
<tr style="background: blue">
{% else %}
<tr>
{% endif %}
<td>{{ loop.index }}</td>
<td>{{ book.name }}</td>
<td>{{ book.author }}</td>
<td>{{ book.price }}</td>
<td>{{ loop.length }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</table>
<table border="1px">
<tbody>
{% for x in range(1,10) %}
<tr>
{% for y in range(1,x+1) if y <= x %}
<td>{{ y }}*{{ x }}={{ x*y }}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
</body>
</html>

模板中的宏跟python中的函数类似,可以传递参数,但是不能有返回值

使用宏的时候,参数可以是默认值

小例子:

macro.py

from flask import Flask,render_template
app = Flask(__name__)
app.config['TEMPLATES_AUTO_RELOAD'] = True
app.config['DEBUG'] = True
@app.route('/')
def hello_world():
return render_template('index.html')
if __name__ == '__main__':
app.run(port=9999)

templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Macro</title>
</head>
<body>
{% macro input(name="",value="",type="text") %}
<input type="{{ type }}" name="{{ name }}" value="{{ value }}">
{% endmacro %}
<h1>登陆页面</h1>
<table>
<tbody>
<tr>
<td>用户名:</td>
<td>{{ input('username') }}</td>
</tr>
<tr>
<td>密码:</td>
<td>{{ input('password',type='password') }}</td>
</tr>
<tr>
<td></td>
<td>{{ input(value='提交',type='submit') }}</td>
</tr>
</tbody>
</table>
</body>
</html>

宏的导入

在真实的开发中,会将一些常用的宏单独放在一个文件中,在需要使用的时候,再从这个文件中进行导入。

import语句的用法跟python中的import类似,可以直接import...as...,也可以from...import...或者from...import...as...,假设现在有一个文件,叫做forms.html,里面有两个宏分别为input和textarea,如下:

注意事项:

a. inport宏文件 as xxx

b. from 宏文件路径 import 宏的名字 [as xxx]

c. 宏文件的路径,不要以相对路径去找,都要以templates作为绝对路径去找

d. 如果想要在导入宏的时候,就把当前末班的一些参数传递给宏所在的模板,那么就应该在导入的时候使用

with context

小例子:

macros.py

from flask import Flask,render_template
app = Flask(__name__)
app.config['TEMPLATES_AUTO_RELOAD'] = True
app.config['DEBUG'] = True
@app.route('/')
def hello_world():
return render_template('index/index.html')
if __name__ == '__main__':
app.run(port=9999)

templates/macros/macros.html

{% macro input(name="",value="",type="text") %}
<input type="{{ type }}" name="{{ name }}" value="{{ username }}">
{% endmacro %}

templates/index/index.html

{#{% from "macros.html" import input as inp %}#}
{% import "macros/macros.html" as macros with context %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Macro</title>
</head>
<body>
<h1>登陆页面</h1>
<table>
<tbody>
<tr>
<td>用户名:</td>
<td>{{ macros.input('username') }}</td>
</tr>
<tr>
<td>密码:</td>
<td>{{ macros.input('password',type='password') }}</td>
</tr>
<tr>
<td></td>
<td>{{ macros.input(value='提交',type='submit') }}</td>
</tr>
</tbody>
</table>
</body>
</html>

include标签

这个标签相当于是将指定模板中的代码复制粘贴到当前的位置

include标签,如果要继续使用父模板中的变量,直接用就可以了

include的路径也和import一样,需要从templates为根,不要以相对路径去找。

小例子:

include_ex.py

from flask import Flask,render_template
app = Flask(__name__)
app.config['TEMPLATES_AUTO_RELOAD']
@app.route('/')
def hello_world():
return render_template('index.html',username='wanghui')
@app.route('/detail/')
def detail():
return render_template('course_detail.html')
if __name__ == '__main__':
app.run(debug=True)

templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>MyBlog</title>
</head>
<body>
{% include "common/header.html" %}
<div class="content">中间的</div>
{% include "common/footer.html" %}
<ul>{{ username }}</ul>
</body>
</html>

templates/course_detail.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% include "common/header.html" %}
<div class="content">文章详情!</div>
{% include "common/footer.html" %}
</body>
</html>

templates/common/header.html

<style>
.nav ul{
overflow: hidden;
}
.nav ul li{
float: left;
margin: 0 20px;
}
</style>
<nav class="nav">
<ul>
<li>首页</li>
<li>博客详情</li>
<li>教程中心</li>
<li>关于我</li>
</ul>
</nav>

templates/common/footer.html

<footer>这是底部</footer>

set with语句

在模板中,可以使用set来定义变量;一旦定义了这个变量。那么在后面的代码中,都可以使用这个变量。

with语句定义的变量,只能在with的代码块中使用。超出with代码块,则不能使用

with不一定要跟一个变量,也可以是一个空的with语句,以后要用的话,就在with中使用set定义的变量来使用。

<body>
{% set username='wanghui' %}
<p>用户名:{{ username }}</p>
{% with %}
{% set classroom='2018' %}
<p>班级:{{ classroom }}</p>
{% endwith %}
<p>别的班级{{ classroom }}</p>
</body>

加载静态文件

加载静态文件使用的是url_for函数,第一个参数为static,第二个参数是filename='path'

路径查找要以static目录作为根目录

小例子:

static_ex.py

from flask import Flask,render_template
app = Flask(__name__)
app.config.update({
'DEBUG':True,
'TEMPLATES_AUTO_RELOAD':True,
})
@app.route('/')
def hello_world():
return render_template('index.html')
if __name__ == '__main__':
app.run()

static/css/index.css

body{
background: pink;
}

static/js/index.js

alert('hello user!')

 

templates/index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{{ url_for('static',filename="css/index.css") }}">
<script src="{{ url_for('static',filename="js/index.js") }}"></script>
</head>
<body>
<img src="{{ url_for('static',filename='imgs/asa.jpg') }}" alt="">
</body>
</html>

模板继承

为什么需要模板继承?

可以将一些公用的代码单独抽取出来放到一个父模板中,以后子模板直接继承就给可以使用了。

这样可以减少重复性的代码,并且以后代码修改起来也很方便

模板继承的语法

使用extends语句来指明继承的父模板。父模板的路径也就是相对于templates文件夹下的绝对路径。例子如下{% extends 'base.html' %}

block语法

一般在父模板中只能定义一些共性公用的代码,子模板可能要根据不同的需求实现不同的代码。这时候父模板就应该提供一个接口,让子模板来实现。从而实现业务的具体功能。

在父模板中

{% block body_block %}
<p>我是base下的</p>
{% endblock %}

在子模板中

{% block body_block %}
<p>我是index的内容</p>
{% endblock %}

调用父模板代码block中的代码

默认情况下,字幕版实现了父模板定义的block,那么子模板中block的代码就会覆盖掉父模板中的代码,要想保留父模板中的block的话就是用{{ super() }}来实现

父模板的内容:

{% block body_block %}
<p style="background: red">base.html</p>
{% endblock %}

子模板中的内容:

{% extends 'base.html' %}
{% block body_block %}
{{ super() }}
<p style="background: green">我是index的内容</p>
{% endblock %}

调用另外一个block中的代码

在另外一个模板中使用其他模板中的代码,可以使用{{ self.blockname() }}即可

父模板

<title>{% block title %}
{% endblock %}</title>
<body>
{% block body_block %}
<p style="background: red">base.html</p>
{% endblock %}
</body>

子模板:

{% extends 'base.html' %}
{% block title %}
MyIndex
{% endblock %}
{% block body_block %}
{{ super() }}
{{ self.title() }}
<p style="background: green">我是index的内容</p>
{% endblock %}

其他注意事项

继承的代码必须放在子模板中的第一行{% extends 'base.html' %}

子模板中要实现自己的代码,要放到block中,不然不生效

继承的例子:

inherit_ex.py

from flask import Flask,render_template
app = Flask(__name__)
app.config.update({
'DEBUG':True,
'TEMPLATES_AUTO_RELOAD':True
})
@app.route('/')
def index():
return render_template('index.html')
@app.route('/detail/')
def detail():
return render_template('course_detail.html')
if __name__ == '__main__':
app.run()

templates/base.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}
{% endblock %}</title>
<style>
.nav ul{
overflow: hidden;
}
.nav ul li{
float: left;
margin: 0 20px;
}
</style>
</head>
<body>
<nav class="nav">
<ul>
<li>首页</li>
<li>博客详情</li>
<li>教程中心</li>
<li>关于我</li>
</ul>
</nav>
{% block body_block %}
<p style="background: red">base.html</p>
{% endblock %}
<footer>这是底部</footer>
</body>
</html>

templates/index.html

{% extends 'base.html' %}
{% block title %}
MyIndex
{% endblock %}
{% block body_block %}
{{ super() }}
{{ self.title() }}
<p style="background: green">我是index的内容</p>
{% endblock %}

templates/course_detail.html

{% extends 'base.html' %}
{% block body_block %}
<p>this is course </p>
{% endblock %}
 
   
次浏览       
相关文章

手机软件测试用例设计实践
手机客户端UI测试分析
iPhone消息推送机制实现与探讨
Android手机开发(一)
相关文档

Android_UI官方设计教程
手机开发平台介绍
android拍照及上传功能
Android讲义智能手机开发
相关课程

Android高级移动应用程序
Android系统开发
Android应用开发
手机软件测试