jinja2过滤器
语法是{{ name| length }}
,将返回name的长度。过滤器相当于一个函数,把当前的变量传入到过滤器中,然后过滤器根据自己的功能,再返回相应的值,之后再将结果渲染到页面中。jinja2中内置了许多过滤器,在这里可以看到所有的过滤器,现对一些常用的过滤器讲解:
- 有时候我们想要在模版中对一些变量进行处理,那么就必须需要类似于Python中的函数一样,可以将这个值传到函数中,然后做一些操作。在模版中,过滤器相当于是一个函数,把当前的变量传入到过滤器中,然后过滤器根据自己的功能,再返回相应的值,之后再将结果渲染到页面中。
- 基本语法:
{{ variable|过滤器名字 }}
。使用管道符号|
进行组合。
常用过滤器:
过滤器 | 功能 | |
---|---|---|
`{{ value | abs}}` | 返回绝对值 |
`{{ value | default(‘默认值’, boolean=True) }}` | 返回默认值 |
{{ value or '默认值' }} |
等价上面 | |
`{{ value | escape }}` | 转义字符,将< > 等符号转义成HTML中的符号 |
`{{ value | safe }}` | 标记为安全,不会转义(关闭自动转义) |
{{ value or '默认值' }} |
等价上面 | |
{{ value or '默认值' }} |
等价上面 |
自动转义过滤器:
safe
过滤器:可以关闭一个字符串的自动转义。escape
过滤器:对某一个字符串进行转义。autoescape
标签,可以对他里面的代码块关闭或开启自动转义。
{% autoescape off/on %}
...代码块
{% endautoescape %}
for循环
Jinja2
中的for
循环包含以下变量,可以用来获取当前的遍历状态;
变量 | 描述 |
---|---|
loop.index | 当前迭代的索引(从1开始) |
loop.index0 | 当前迭代的索引(从0开始) |
loop.first | 是否是第一次迭代,返回True或者False |
loop.last | 是否是最后一次迭代,返回True或者False |
loop.length | 序列的长度 |
另外:不支持continue
和break
表达式来控制循环的执行
常用过滤器:
- 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):计算一个长字符串中单词的个数。
自定义模版过滤器:
过滤器本质上就是一个函数。如果在模版中调用这个过滤器,那么就会将这个变量的值作为第一个参数传给过滤器这个函数,然后函数的返回值会作为这个过滤器的返回值。需要使用到一个装饰器:
@app.template_filter('cut')`
# python
@app.template_filter('cut')
def cut(value):
value = value.replace("hello",'')
return value
# html
<p>{{ article|cut }}</p>
宏
模板中的宏跟python中的函数类似,可以传递参数,但是不能有返回值,可以将一些经常用到的代码片段放到宏中,然后把一些不固定的值抽取出来当成一个变量。
使用宏的时候,参数可以为默认值。相关示例代码如下:
- 定义宏:
{% macro input(name, value='', type='text') %}
<input type="{{ type }}" name="{{ name }}" value="{{
value }}">
{% endmacro %}
- 使用宏:
<p>{{ input('username') }}</p>
<p>{{ input('password', type='password') }}</p>
导入宏:
import "宏文件的路径" as xxx
。from '宏文件的路径' import 宏的名字 [as xxx]
。- 宏文件路径,不要以相对路径去寻找,都要以
templates
作为绝对路径去找。 - 如果想要在导入宏的时候,就把当前模版的一些参数传给宏所在的模版,那么就应该在导入的时候使用
with context
。示例:from 'xxx.html' import input with context
。
# 第一种方式
{% import 'macro.html' as macro %}
使用方式:
{{ macron.input('username') }}
# 第二种方式
{% from 'macro.html' import input as input_filed %}
使用方式:
{{ input_filed('username') }}
include标签:
- 导入指定模板的代码到当前位置
include
标签,如果想要使用父模版中的变量,直接用就可以了,不需要使用with context
。include
的路径,也是跟import
一样,直接从templates
根目录下去找,不要以相对路径去找。
使用代码如下:
{% include 'common/head.html' %}
<div class="content">
我是内容的地址哦
</div>
{% include 'common/footView.html' %}
定义变量
- 定义全局变量:
{% set username='深圳大学' %}
- 定义局部变量:
{% with classroom = '软件工程' %} 仅此区间可以使用变量 classroom {% endwith %}
导入静态文件
加载css文件: {{ url_for('static', filename='/css/index.css') }}
加载js文件: {{ url_for('static', filename='/js/index.js') }}
加载图片文件: {{ url_for('static', filename='/imgs/flower.jpg') }}
模板继承
注意事项:
- 继承模板的代码一定要在最前面导入
{% extends 'base.html' %}
- 子模板中,如果要实现自己的代码,应该放到了block中。放在block之外,不会被渲染
{% extends 'base.html' %}
{% block title %} 首页标题 {% endblock %}
{% block body_block %}
{{ super() }}
{{ self.title() }}
{% endblock %}
set和with
set
语句
set
在模板中可以定义变量,后面想要使用的时候,直接使用,例子如下:
{% set username = '我只是想学好后台开发,你们觉得好不好' %}
<div class="test">
{{ username }}
</div>
with
语句
with
只能在其作用域名中使用
{% with classroom = 'test is very import' %}
{{ classroom }}
{% endwith %}
视图高级
add_url_rule
函数
语法: add_url_rule(*args, **kwargs)
装饰器 @app.route(rule, **option)
底层调用的 add_url_rule()
函数
最佳实践: 添加 endpoint 参数
from flask import Falsk, url_for
app = Flask(__name__)
@app.route('/') # @app.route('/', endpoint='index')
def hello():
return 'Hello World!'
def list():
return '我是列表页面'
app.add_url_rule('list', endpoint='list', view_func=list)
类视图
标准类视图
- 标准类视图,必须继承自
flask.views.View
- 必须实现
dispatch_request
方法:以后请求过来后,都会执行这个方法。这个方法的返回值就相当于是之前的函数视图一样。也必须返回Response或者子类的对象。或者是字符串,或者是元组
- 必须映射:通过
app_add_url_rule(rule, endpoint, view_func)
来做url与视图的映射。view_func
参数,需要使用类视图下的as_view
类方法一转换:ListView.as_view('list')
from flask import Flask, views
class ListView(views.View):
def dispatch_request(self):
return 'this is list view class'
app.add_url_rule('/list/', endpoint='list', view_func=ListView.as_view('list'))
事例:
# 事例1 - 有几个url需要返回json数据
class JSONView(views.View):
def get_data(self):
raise NotImplementedError
def dispatch_request(self):
return jsonify(self.get_data())
def ListView(JSONView):
def get_data(selfl):
return {'username': 'zhangsan', 'password': '111111'}
app.add_url_rule('/list', endpoint='my_list', view_func=ListView.as_view('list'))
# 事例2 - 有几个视图需要返回相同的变量
class ADSView(views.View):
def __init__(self):
super().__init__()
self.context = {
'今年过节不收礼'
}
class LoginView(ADSView):
def dispatch_request(self):
self.context.update({
'username': 'zhangsan'
})
return renader_template('login.html', **self.context)
class RegistView(ADSView):
def dispatch_requet(self):
return render_template('regist.html', **self.context)
基于调度方法的类视图
flask.views.MethodView
,对每个HTTP方法执行不同的函数(映射到对应方法的小写的同名方法上),这对RESTful API 尤其有用,以下将用一个例子来进行讲解:
基于方法的类视图,是根据请求的method
来执行不同的方法。
- 如果用户是发送的
get
请求,那么将会执行这个类的get
方法 - 如果用户是秘关的
post
请求,那么将公执行这个类的post
方法。
class LoginView(views.MethodView):
def __render(self, error=None)
return render_template('login.html', error=error)
def get(self):
return self.__render()
def post(self):
username = request.form.get('username')
password = request.form.get('password')
if username == 'zhangsan' and password == '111111':
return 'login success'
else:
return self.__render(error='用户名或者密码有误s')
类视图使用装饰器
- 如果使用的是函数视图,那么定义的装饰器必须放在
app.route
下面。否则这个装饰器就起不到作用 - 类视图装饰器,需要重写类视图的一个类属性
decorators
,这个类属性是一个列表或者元组都可以
# 1. 普通函数装饰器
def login_required(func):
@wraps(func)
def wrapper(*args, **kwargs):
username = request.args.get('username')
if username and username == 'zhangsan':
return func(*args, **kwargs)
else:
return '请先登录'
return wrapper
@app.route('/')
@login.required # 使用函数视图时,装饰器必须放在 app.route下面
def hello():
return 'Hello World'
# login_required(app.route('/')(hello)) 装饰器在app.route上面时
# app.route('/')(login_required(hello)) 装饰器在app.route下面时
# 2. 类视图装饰器
class ProfileView(views.View):
decorators = [login_required] # 类视图装饰器需要声明此变量
def dispatch_request(self):
return '这是个人中心页面'
app.add_url_rule('/profile/', view_func=ProfileView.as_view('profile'))
定义
1.定义的类必须继承views.view
和重写dispatch_request
的方法。
from flask import Flask,views
app = Flask(__name__)
class ListView(views.View):
def dispatch_request(self):
return 'list View
2.最后通过add_url_rule
进行添加
app.add_url_rule('/list/',endpoint='list',view_func=ListView.as_view('list'))
3.如果设置endpoint
使用url_for
的时候就使用endpoint
的值,如果没有设置就使用view_func
中设置的值.注意as_view('list')
必须设置名字.
#####使用
- 比如某些视图类需要返回的数据是
json
,使用如下
class JSONView(views.View):
def get_data(self):
raise NotImplementedError
def dispatch_request(self):
return jsonify(self.get_data())
class ListView(JSONView):
def get_data(self):
return ['test','fsdljfsl','shenmguio']
app.add_url_rule('/list/',view_func=ListView.as_view('fuck'))