jinja2过滤器

语法是{{ name| length }},将返回name的长度。过滤器相当于一个函数,把当前的变量传入到过滤器中,然后过滤器根据自己的功能,再返回相应的值,之后再将结果渲染到页面中。jinja2中内置了许多过滤器,在这里可以看到所有的过滤器,现对一些常用的过滤器讲解:

  1. 有时候我们想要在模版中对一些变量进行处理,那么就必须需要类似于Python中的函数一样,可以将这个值传到函数中,然后做一些操作。在模版中,过滤器相当于是一个函数,把当前的变量传入到过滤器中,然后过滤器根据自己的功能,再返回相应的值,之后再将结果渲染到页面中。
  2. 基本语法:{{ variable|过滤器名字 }}。使用管道符号|进行组合。

常用过滤器:

过滤器 功能
`{{ value abs}}` 返回绝对值
`{{ value default(‘默认值’, boolean=True) }}` 返回默认值
{{ value or '默认值' }} 等价上面
`{{ value escape }}` 转义字符,将< >等符号转义成HTML中的符号
`{{ value safe }}` 标记为安全,不会转义(关闭自动转义)
{{ value or '默认值' }} 等价上面
{{ value or '默认值' }} 等价上面

自动转义过滤器:

  1. safe过滤器:可以关闭一个字符串的自动转义。
  2. escape过滤器:对某一个字符串进行转义。
  3. autoescape标签,可以对他里面的代码块关闭或开启自动转义。
  1. {% autoescape off/on %}
  2. ...代码块
  3. {% endautoescape %}

for循环

Jinja2中的for循环包含以下变量,可以用来获取当前的遍历状态;

变量 描述
loop.index 当前迭代的索引(从1开始)
loop.index0 当前迭代的索引(从0开始)
loop.first 是否是第一次迭代,返回True或者False
loop.last 是否是最后一次迭代,返回True或者False
loop.length 序列的长度

另外:不支持continuebreak表达式来控制循环的执行

常用过滤器:

  1. first(value):返回一个序列的第一个元素。names|first。
    format(value,arags,*kwargs):格式化字符串。例如以下代码:

{{ "%s" - "%s"|format('Hello?',"Foo!")

将输出:Helloo? - Foo!

  1. last(value):返回一个序列的最后一个元素。示例:names|last。
  2. length(value):返回一个序列或者字典的长度。示例:names|length。
  3. join(value,d=u’’):将一个序列用d这个参数的值拼接成字符串。
  4. safe(value):如果开启了全局转义,那么safe过滤器会将变量关掉转义。示例:content_html|safe。
  5. int(value):将值转换为int类型。
  6. float(value):将值转换为float类型。
  7. lower(value):将字符串转换为小写。
  8. upper(value):将字符串转换为小写。
  9. replace(value,old,new): 替换将old替换为new的字符串。
  10. truncate(value,length=255,killwords=False):截取length长度的字符串。
  11. striptags(value):删除字符串中所有的HTML标签,如果出现多个空格,将替换成一个空格。
  12. trim:截取字符串前面和后面的空白字符。
  13. string(value):将变量转换成字符串。
  14. wordcount(s):计算一个长字符串中单词的个数。

自定义模版过滤器:

过滤器本质上就是一个函数。如果在模版中调用这个过滤器,那么就会将这个变量的值作为第一个参数传给过滤器这个函数,然后函数的返回值会作为这个过滤器的返回值。需要使用到一个装饰器:

  1. @app.template_filter('cut')`
  2. # python
  3. @app.template_filter('cut')
  4. def cut(value):
  5. value = value.replace("hello",'')
  6. return value
  7. # html
  8. <p>{{ article|cut }}</p>

模板中的宏跟python中的函数类似,可以传递参数,但是不能有返回值,可以将一些经常用到的代码片段放到宏中,然后把一些不固定的值抽取出来当成一个变量。
使用宏的时候,参数可以为默认值。相关示例代码如下:

  1. 定义宏:
  1. {% macro input(name, value='', type='text') %}
  2. <input type="{{ type }}" name="{{ name }}" value="{{
  3. value }}">
  4. {% endmacro %}
  1. 使用宏:
  1. <p>{{ input('username') }}</p>
  2. <p>{{ input('password', type='password') }}</p>

导入宏:

  1. import "宏文件的路径" as xxx
  2. from '宏文件的路径' import 宏的名字 [as xxx]
  3. 宏文件路径,不要以相对路径去寻找,都要以templates作为绝对路径去找。
  4. 如果想要在导入宏的时候,就把当前模版的一些参数传给宏所在的模版,那么就应该在导入的时候使用with context。示例:from 'xxx.html' import input with context
  1. # 第一种方式
  2. {% import 'macro.html' as macro %}
  3. 使用方式:
  4. {{ macron.input('username') }}
  5. # 第二种方式
  6. {% from 'macro.html' import input as input_filed %}
  7. 使用方式:
  8. {{ input_filed('username') }}

include标签:

  1. 导入指定模板的代码到当前位置
  2. include标签,如果想要使用父模版中的变量,直接用就可以了,不需要使用with context
  3. include的路径,也是跟import一样,直接从templates根目录下去找,不要以相对路径去找。

使用代码如下:

  1. {% include 'common/head.html' %}
  2. <div class="content">
  3. 我是内容的地址哦
  4. </div>
  5. {% 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') }}

模板继承

注意事项:

  1. 继承模板的代码一定要在最前面导入 {% extends 'base.html' %}
  2. 子模板中,如果要实现自己的代码,应该放到了block中。放在block之外,不会被渲染
  1. {% extends 'base.html' %}
  2. {% block title %} 首页标题 {% endblock %}
  3. {% block body_block %}
  4. {{ super() }}
  5. {{ self.title() }}
  6. {% endblock %}

set和with

set语句

set在模板中可以定义变量,后面想要使用的时候,直接使用,例子如下:

  1. {% set username = '我只是想学好后台开发,你们觉得好不好' %}
  2. <div class="test">
  3. {{ username }}
  4. </div>

with语句

with只能在其作用域名中使用

  1. {% with classroom = 'test is very import' %}
  2. {{ classroom }}
  3. {% endwith %}

视图高级

add_url_rule函数

语法: add_url_rule(*args, **kwargs)

装饰器 @app.route(rule, **option) 底层调用的 add_url_rule()函数

最佳实践: 添加 endpoint 参数

  1. from flask import Falsk, url_for
  2. app = Flask(__name__)
  3. @app.route('/') # @app.route('/', endpoint='index')
  4. def hello():
  5. return 'Hello World!'
  6. def list():
  7. return '我是列表页面'
  8. app.add_url_rule('list', endpoint='list', view_func=list)

类视图

标准类视图
  1. 标准类视图,必须继承自flask.views.View
  2. 必须实现dispatch_request方法:以后请求过来后,都会执行这个方法。这个方法的返回值就相当于是之前的函数视图一样。也必须返回Response或者子类的对象。或者是字符串,或者是元组
  3. 必须映射:通过app_add_url_rule(rule, endpoint, view_func)来做url与视图的映射。view_func参数,需要使用类视图下的as_view类方法一转换:ListView.as_view('list')
  1. from flask import Flask, views
  2. class ListView(views.View):
  3. def dispatch_request(self):
  4. return 'this is list view class'
  5. app.add_url_rule('/list/', endpoint='list', view_func=ListView.as_view('list'))

事例:

  1. # 事例1 - 有几个url需要返回json数据
  2. class JSONView(views.View):
  3. def get_data(self):
  4. raise NotImplementedError
  5. def dispatch_request(self):
  6. return jsonify(self.get_data())
  7. def ListView(JSONView):
  8. def get_data(selfl):
  9. return {'username': 'zhangsan', 'password': '111111'}
  10. app.add_url_rule('/list', endpoint='my_list', view_func=ListView.as_view('list'))
  11. # 事例2 - 有几个视图需要返回相同的变量
  12. class ADSView(views.View):
  13. def __init__(self):
  14. super().__init__()
  15. self.context = {
  16. '今年过节不收礼'
  17. }
  18. class LoginView(ADSView):
  19. def dispatch_request(self):
  20. self.context.update({
  21. 'username': 'zhangsan'
  22. })
  23. return renader_template('login.html', **self.context)
  24. class RegistView(ADSView):
  25. def dispatch_requet(self):
  26. return render_template('regist.html', **self.context)

基于调度方法的类视图

flask.views.MethodView,对每个HTTP方法执行不同的函数(映射到对应方法的小写的同名方法上),这对RESTful API 尤其有用,以下将用一个例子来进行讲解:

基于方法的类视图,是根据请求的method来执行不同的方法。

  • 如果用户是发送的get请求,那么将会执行这个类的get方法
  • 如果用户是秘关的post请求,那么将公执行这个类的post方法。
  1. class LoginView(views.MethodView):
  2. def __render(self, error=None)
  3. return render_template('login.html', error=error)
  4. def get(self):
  5. return self.__render()
  6. def post(self):
  7. username = request.form.get('username')
  8. password = request.form.get('password')
  9. if username == 'zhangsan' and password == '111111':
  10. return 'login success'
  11. else:
  12. return self.__render(error='用户名或者密码有误s')

类视图使用装饰器

  1. 如果使用的是函数视图,那么定义的装饰器必须放在app.route下面。否则这个装饰器就起不到作用
  2. 类视图装饰器,需要重写类视图的一个类属性decorators,这个类属性是一个列表或者元组都可以
  1. # 1. 普通函数装饰器
  2. def login_required(func):
  3. @wraps(func)
  4. def wrapper(*args, **kwargs):
  5. username = request.args.get('username')
  6. if username and username == 'zhangsan':
  7. return func(*args, **kwargs)
  8. else:
  9. return '请先登录'
  10. return wrapper
  11. @app.route('/')
  12. @login.required # 使用函数视图时,装饰器必须放在 app.route下面
  13. def hello():
  14. return 'Hello World'
  15. # login_required(app.route('/')(hello)) 装饰器在app.route上面时
  16. # app.route('/')(login_required(hello)) 装饰器在app.route下面时
  17. # 2. 类视图装饰器
  18. class ProfileView(views.View):
  19. decorators = [login_required] # 类视图装饰器需要声明此变量
  20. def dispatch_request(self):
  21. return '这是个人中心页面'
  22. app.add_url_rule('/profile/', view_func=ProfileView.as_view('profile'))

定义

1.定义的类必须继承views.view 和重写dispatch_request的方法。

  1. from flask import Flask,views
  2. app = Flask(__name__)
  3. class ListView(views.View):
  4. def dispatch_request(self):
  5. return 'list View

2.最后通过add_url_rule进行添加

  1. app.add_url_rule('/list/',endpoint='list',view_func=ListView.as_view('list'))

3.如果设置endpoint使用url_for的时候就使用endpoint的值,如果没有设置就使用view_func中设置的值.注意as_view('list')必须设置名字.
#####使用

  1. 比如某些视图类需要返回的数据是json,使用如下
  1. class JSONView(views.View):
  2. def get_data(self):
  3. raise NotImplementedError
  4. def dispatch_request(self):
  5. return jsonify(self.get_data())
  6. class ListView(JSONView):
  7. def get_data(self):
  8. return ['test','fsdljfsl','shenmguio']
  9. app.add_url_rule('/list/',view_func=ListView.as_view('fuck'))