未命名作品.jpg


1 重定向

1.1 什么是重定向?

重定向,顾名思义,就是重新定向到一个新的位置,比如我们在浏览器的页面自动跳转到了另一个页面,又比如访问了一个页面,然后观察网址之后并不是我们输入的网址,这个过程就是重定向完成的。

1.2 为什么要有重定向?

http状态码 应用场景 优势
暂时性重定向 302 访问一些需要权限的页面,会自动重定向到权限认证的页面 重定向在设计上会提升用户体验
永久性重定向 301 废弃原有的网址被访问,会自动重定向到新的网址确保用户访问成功 重定向在设计上会提升用户体验,有利于搜索引擎优化

例1:访问淘宝的时候,你选择了已经购买的商品,但是你并没有登录过淘宝,那么这个时候如果只是提示 “请登录再访问!”,那么相信这种设计是留不住用户的,不如直接为用户重定向到登录页面。
例2:比如想废弃原本的网址,那么用户并不知道这个事情,所以用户还是会访问原来的网址,那么就会内部做一个重定向到新启用的网址,重定向的过程会有状态码的返回,搜索引擎捕捉到重定向的代码,有利于搜索引擎优化。
关键词:重定向在设计上会提升用户体验 ,有利于搜索引擎优化

1.3 如何使用重定向?

首先从flask模块中把导入redirect

  1. from flask import Flask,redirect

1.3.1 暂时性重定向(代码实例):

  1. from flask import Flask,redirect
  2. ...
  3. @app.route('/user_info/')
  4. def user_info():
  5. name = request.args.get('name')
  6. pwd = request.args.get('pwd')
  7. if name=='mark' and pwd == '123':
  8. return '{}的信息'.format(name)
  9. return redirect('/login/') # 可以换成 return redirect(url_for('login'))
  10. @app.route('/login/')
  11. def login():
  12. return '这是登录页面'
  13. ...

没有通过权限验证的情况
04-01 模板 - 图2
04-01 模板 - 图3
通过权限验证的情况
04-01 模板 - 图4
关键词:暂时性重定向return redirect('/login/') 即可实现重定向

1.3.2 永久性重定向(代码实例)

  1. from flask import Flask,redirect
  2. ...
  3. @app.route('/user_info/')
  4. def user_info():
  5. name = request.args.get('name')
  6. pwd = request.args.get('pwd')
  7. if name=='mark' and pwd == '123':
  8. return '{}的信息'.format(name)
  9. return redirect('/login/', code=301) # 会返回301状态码给浏览器
  10. @app.route('/login/')
  11. def login():
  12. return '这是登录页面'
  13. ...

关键词:永久性重定向只给redirect('/login/', code=301)多加了个code=301参数

2 jinja2模板引擎

2.1 什么是模板引擎?

实现视图的业务逻辑和返回给前端的页面逻辑分离的工具,我们称之为模板引擎。
什么是模板?
模板可以理解为一个特殊的html文件,特殊之处就在于这个html文件包含固定内容和动态部分,其动态部分可以借助模板引擎进行传参

2.2 为什么要有模板引擎?

在上一章其实我们已经应用过模板引擎,试想一下如果没有模板引擎,直接给把模板的html代码写在视图函数里面,会给程序员的日常开发带来了多大的困扰,模板引擎帮我们分开了业务逻辑和页面逻辑,并且我们每次修改一个大字符串会非常不方便。模板引擎还可以读取并执行模板中的特殊语法标记,并根据传入的数据将变量替换为实际值,然后返回给浏览器,这个过程我们称之为渲染。
关键字:完成了业务逻辑和页面逻辑的分离,实现了动态的去渲染页面。

2.3 在Flask如何使用模板引擎?

Flask使用jinja2作为框架的默认模板引擎,Jinja2是基于python的模板引擎,功能比较类似于于PHPsmartyJ2eeFreemarkervelocityJinja2除了设置变量,还允许我们在模板中添加if判断,执行for迭代,调用函数等,以各种方式控制模板的输出。并且jinja2不限制模板的格式为html,可以是任何格式的文本文件。

2.3.1 模板引擎返回对比视图函数直接返回html代码

项目目录
04-01 模板 - 图5
项目代码
(1)login01.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>登录界面</title>
  6. </head>
  7. <body>
  8. <h1>login01</h1> <!--login02.html文件的这一行的内容是:‘ <h1>login02</h1> ’ -->
  9. <form action="" method="POST">
  10. 用户:<input type="text" name="username">
  11. 密码:<input type="text" name="password">
  12. <input type="submit" value="提交">
  13. </form>
  14. </body>
  15. </html>

(2)login02.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>登录界面</title>
  6. </head>
  7. <body>
  8. <h1>login01</h1> <!--login02.html文件的这一行的内容是:‘ <h1>login02</h1> ’ -->
  9. <form action="" method="POST">
  10. 用户:<input type="text" name="username">
  11. 密码:<input type="text" name="password">
  12. <input type="submit" value="提交">
  13. </form>
  14. </body>
  15. </html>

(3) server.py

  1. from flask import Flask, render_template
  2. import config
  3. app = Flask(__name__)
  4. app.config.from_object(config)
  5. @app.route('/demo/')
  6. def demo():
  7. return '<h2>手写html</h2>'
  8. @app.route('/demo02/')
  9. def demo02():
  10. return '''<!DOCTYPE html>
  11. <html lang="en">
  12. <head>
  13. <meta charset="UTF-8">
  14. <title>登录界面</title>
  15. </head>
  16. <body>
  17. <!--<form action="/login_request/" method="POST">-->
  18. <form action="" method="POST">
  19. 用户:<input type="text" name="username">
  20. 密码:<input type="text" name="password">
  21. <input type="submit" value="提交">
  22. </form>
  23. </body>
  24. </html>'''
  25. @app.route('/demo03/')
  26. def demo03():
  27. return render_template('login01.html')
  28. @app.route('/demo04/')
  29. def demo04():
  30. return render_template('box/login02.html')
  31. if __name__ == '__main__':
  32. app.run()

server.py代码逻辑分析

  • demo函数 和 demo02函数证明直接返回html代码可渲染浏览器
  • demo03 证明利用模板引擎 实现了业务逻辑和页面逻辑的分离,减轻了开发的复杂度
  • demo04 证明了 render_template('box/login02.html')的路径是templates文件夹的相对路径

    2.3.2 修改默认模板引擎寻找路径

    Flask类中的template_folder参数可以指定模板寻找路径
    基于上2.3.1的项目
  1. 现在把templates中的文件复制到 C:/Users/Administrator/Desktop/template_box中,并且删除项目中的templates的文件。
  2. 修改server.py中app = Flask(__name__)app = Flask(__name__,template_folder='C:/Users/Administrator/Desktop/template_box')

分析:
渲染一切正常 说明Flask类中的template_folder参数可以指定模板寻找路径。

2.3.3 模板引擎传参

我们之前提到过,模板引擎还可以读取并执行模板中的特殊语法标记,并根据传入的数据将变量替换为实际值,这个步骤我们就称之为模板引擎传参。
我们传参的时候要应用render_template()利用render_template的第二个参数进行传参,该函数在定义时候,第二个参数是可变长形参,所以在传值的时候我们可以传入多个关键字实参。
在模板中接收的时候使用{{}}包裹参数进行接收。

实例1(第一种传参方式):

目录结构

  1. server.py
  2. └─templates # 文件夹
  3. index.html

server.py

  1. @app.route('/')
  2. def index():
  3. return render_template('index.html',name="mark",age=18)

index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>模板传参</title>
  6. </head>
  7. <body>
  8. {{name}}
  9. {{age}}
  10. </body>
  11. </html>

04-01 模板 - 图6

实例2(第二种传参方式):

目录结构:同上
server.py

  1. @app.route('/demo1/')
  2. def demo1():
  3. context_dict = {"name":"mark",
  4. "age":"mark",
  5. "sex":"girl"}
  6. return render_template('index.html',context_dict = context_dict)

index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>模板传参</title>
  6. </head>
  7. <body>
  8. {{context_dict.name}}
  9. {{context_dict.age}}
  10. {{context_dict.sex}}
  11. </body>
  12. </html>

04-01 模板 - 图7

实例3(第三种传参方式):

目录结构:同上
server.py

  1. def demo2():
  2. context_dict = {"name": "mark",
  3. "age": "mark",
  4. "sex": "girl",
  5. "other_info":{"tel":1365,
  6. "qq":565656}}
  7. return render_template('index.html',**context_dict)

index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>模板传参</title>
  6. </head>
  7. <body>
  8. {{name}}
  9. {{age}}
  10. {{sex}}
  11. {{other_info.tel}}
  12. {{other_info["qq"]}}
  13. </body>
  14. </html>

04-01 模板 - 图8

关键词:

在视图函数中

  • render_template传参的时候以关键字实参进行传参。可以传多个,可以用**讲字典打散成关键字实参。

在模板中

  • jinja2模板引擎支持接收变量在用 {{}}包裹参数进行接收
  • 并且如果发现是字典,可以用.字典里面的key取出value值。也可以直接字典跟[]进行取值。

    2.3.4模板中使用url_for()

    在模板中如果有使用url的需求,我们可以直接手写一个url,也可以使用{{ url_for('视图函数名') }动态翻转一个url。
    实例:
    项目目录: ```python │ server.py │ └─templates # 文件夹
    1. index.html
    2. info.html
  1. **server.py**
  2. ```python
  3. ...
  4. @app.route('/')
  5. def index():
  6. return render_template('index.html', name="mark", age=18)
  7. @app.route('/info/')
  8. def info():
  9. return render_template('info.html')
  10. ...

info.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>信息页面</title>
  6. </head>
  7. <body>
  8. <h1>这是信息页面</h1>
  9. </body>
  10. </html>

index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>模板传参</title>
  6. </head>
  7. <body>
  8. <a href="/info/">正常跳转</a>
  9. <a href="{{ url_for('info') }}">urlfor跳转</a>
  10. </body>
  11. </html>

04-01 模板 - 图9
04-01 模板 - 图10
正常跳转 和 urlfor跳转,皆可以实现跳转到info.html页面。
正常跳转就不做演示了

关键词:
  • url_for 在视图函数中如何使用,在模板中同样的用法。
  • 支持翻转查询字符串
  • 支持动态路由翻转

    2.3.5 jinja2中控制语句

    在jinja2中用{% %}特殊符号来编辑控制语句,一个语句以{% ... %}为起始 并且以{% end... %}来标记结束。
    1 jinja2中逻辑语句/if语句
    可以使用> , < , <=, ==,!=,进行判断,
    也可以使用 and,or,not,()来进行逻辑合并 ```python {% if age > 18 %}
    1. <p>成年人</p>
    {% elif age == 18 %}
    1. <p>刚刚成年</p>
    {% else %}
    1. <p>未成年</p>
    {% endif %}
  1. 注意:`<p>`只是为了渲染明显
  2. <a name="6234fab9-1"></a>
  3. ###### 实例:
  4. **项目目录**:
  5. ```python
  6. │ server.py
  7. └─templates # 文件夹
  8. index.html

server.py

  1. ...
  2. @app.route('/')
  3. def hello_world():
  4. context_dict = {
  5. 'age': 17,
  6. 'sex': 'man',
  7. }
  8. return render_template('index.html',**context_dict)
  9. ...

index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>jinja2分支</title>
  6. </head>
  7. <body>
  8. {% if sex == 'man' %}
  9. <p>男人</p>
  10. {% else %}
  11. <p>女人</p>
  12. {% endif %}
  13. {% if age > 18 %}
  14. <p>成年人</p>
  15. {% elif age == 18 %}
  16. <p>刚刚成年</p>
  17. {% else %}
  18. <p>未成年</p>
  19. {% endif %}
  20. </body>
  21. </html>

04-01 模板 - 图11

2 jinja2中循环语句/for循环

for循环可以便利任何一个可迭代对象,包括列表、字典等,支持反向遍历
列表循环:

  1. {% for country in countrys%}
  2. <p>{{ country }}</p>
  3. {% else %}
  4. <p>没有值</p>
  5. {% endfor %}

2.1 列表循环遍历项目实例:

项目目录:

  1. server.py
  2. └─templates # 文件夹
  3. index.html

sever.py

  1. @app.route('/')
  2. def hello_world():
  3. context_dict = {
  4. 'countrys':["1-china","2-America","3-French"]
  5. }
  6. return render_template('index.html',**context_dict)

index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>for循环</title>
  6. </head>
  7. <body>
  8. {% for country in countrys %} {# {% for country in countrys|reverse %} 可以实现反向遍历#}
  9. <p>{{ country }}</p>
  10. {% else %}
  11. <p>没有值</p>
  12. {% endfor %}
  13. </body>
  14. </html>

04-01 模板 - 图12
反向遍历实例
server.py{% for country in countrys %} 改为 {% for country in countrys|reverse %}
可以实现反向遍历,运行效果如下图
04-01 模板 - 图13

2.2 字典循环遍历项目实例:

项目目录

  1. server.py
  2. └─templates # 文件夹
  3. index.html

sever.py

  1. @app.route('/')
  2. def hello_world():
  3. context_dict = {
  4. 'countrys':["1-china","2-America","3-French"]
  5. }
  6. return render_template('index.html',**context_dict)
  7. @app.route('/demo/')
  8. def demo():
  9. context_dict ={
  10. 'colleges':[
  11. {
  12. 'name': '清华大学',
  13. 'area': '北京'
  14. },
  15. {
  16. 'name': '复旦大学',
  17. 'area': '上海'
  18. ''
  19. },
  20. {
  21. 'name': '吉林大学',
  22. 'area': '吉林'
  23. },
  24. {
  25. 'name': '中山大学',
  26. 'area': '广东'
  27. }
  28. ]
  29. }
  30. return render_template('index.html',**context_dict)

index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>for循环</title>
  6. </head>
  7. <body>
  8. <table>
  9. <tr>
  10. <th>1开始的序号</th>
  11. <th>0开始的序号</th>
  12. <th>大学名称</th>
  13. <th>所属地区</th>
  14. <th>总数</th>
  15. </tr>
  16. {% for college in colleges %}
  17. {% if loop.first %}
  18. <tr style="background: blue">
  19. {% elif loop.last %}
  20. <tr style="background: yellow ">
  21. {% else %}
  22. <tr>
  23. {% endif %}
  24. <td>{{ loop.index }}</td>
  25. <td>{{ loop.index0 }}</td>
  26. <td>{{ college.name }}</td>
  27. <td>{{ college.area }}</td>
  28. <td>{{ loop.length }}</td>
  29. </tr>
  30. {% endfor %}
  31. </table>
  32. </body>
  33. </html>

04-01 模板 - 图14
for循环常用变量表

for循环常用变量 功能描述
loop.index 当前循环的索引(从1开始)
loop.index0 当前循环的索引(从0开始)
loop.first 是否是第一次循环,是返回True,否则返回Flase
loop.last 是否是最后一次循环,是返回True,否则返回Flase
loop.length 总共可以循环的次数 / 迭代器的长度

for循环中的else用法

for还可以else分支语法,如果for内部没有遍历出来内容,那么就会走else分支,反之如果for循环遍历出了内容,则不会运行else分支。
注意:jinja2中的forelse逻辑不通于python在此不要类比python中的 forelse

  1. {% for country in countrys|reverse %}
  2. <p>{{ country }}</p>
  3. {% else %}
  4. <p>没有值</p>
  5. {% endfor %}

2.3.6 模板加载静态文件

在模板中加载静态文件的时候也要使用到url_for()函数,去寻找具体的静态文件资源。第一个参数是定位到static文件夹,filename参数定位到static文件夹内的具体资源。

  1. {{ url_for('static',filename='相对于static文件夹的路径') }}

实例:

项目目录:

  1. app.py
  2. ├─static # 文件夹
  3. ├─css # 文件夹
  4. demo.css
  5. ├─images # 文件夹
  6. 1.png
  7. └─js # 文件夹
  8. demo.js
  9. ├─templates # 文件夹
  10. index.html

app.py

  1. ...
  2. @app.route('/')
  3. def hello_world():
  4. return render_template('index.html')
  5. ...

index.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>静态文件加载</title>
  6. <link rel="stylesheet" href="{{ url_for('static',filename='css/demo.css') }}">
  7. <script src="{{ url_for('static',filename='js/demo.js') }}"></script>
  8. </head>
  9. <body>
  10. <img src="{{ url_for('static',filename='images/1.png') }}">
  11. </body>
  12. </html>

demo.css

  1. body{
  2. background: red;
  3. }

demo.js

  1. alert('hello world')

04-01 模板 - 图15
04-01 模板 - 图16

2.3.7 模板的继承

jinja2的模板继承可以把一些公共的代码定义到一个基模板中,比如把导航栏、页脚等通用内容放在基模板中,以后所有的子模板直接继承基模板,在子模板被渲染时会自动包含继承基模板的内容,通过模板的继承可以避免在多个模板中编写重复的代码。

具体实现:

在基模板中定义一些公共的代码,子模板会继承这些公共的代码,但是子模板需要根据自己的需求去实现不同的代码,这个时候就需要在基模板中提供一些接口,以便子模板实现自己的业务需求。
1 基本写法
在基/父模板中定义接口(block)

  1. {% block main %} {# main是自定义的变量名 #}
  2. {% endblock %}

在子模板中继承父模板,并且重写接口(block)

  1. {% extends 'base.html' %} {# extends 后面跟的参数是导入的基模板相对于templates的路径 #}
  2. {% block main %}
  3. {% endblock %}

2 子模板中调用父模板代码block中的代码
基模板中

  1. {% block main %}
  2. <p>父模板中main中原有的内容</p>
  3. {% endblock %}

子模板中:

  1. {% block main %}
  2. {{ super() }} {# 保留基模板中本块的代码 #}
  3. <p>子模板中重写main的内容 </p>
  4. {% endblock %}

3 在子模板中调用其他block中的代码:
子模板中:

  1. {% block main %}
  2. {{ self.demo() }} {# self.其他block名字 #}
  3. <p>子模板中重写main的内容 </p>
  4. {% endblock %}

4 子模板中的想定义自己的代码只能放到block中,否则无效

实例

注意:这里面我们使用了bootstrap框架。
bootstrap3的中文官网:https://v3.bootcss.com/
1 首先下载 用于生产环境的 Bootstrap
04-01 模板 - 图17
2 解压出来里面的css文件
项目目录

  1. app.py
  2. ├─static # 文件夹
  3. └─css
  4. bootstrap-theme.css
  5. bootstrap-theme.css.map
  6. bootstrap-theme.min.css
  7. bootstrap-theme.min.css.map
  8. bootstrap.css
  9. bootstrap.css.map
  10. bootstrap.min.css
  11. bootstrap.min.css.map
  12. ├─templates # 文件夹
  13. base.html
  14. detail.html

css文件夹: 是从我们上面下载好的用于生产环境的 Bootstrap中解压出来的
base.html 注意:里面的form标签中的内容和nav标签中的内容均是bootstrap框架的代码截取,div标签是用于清除浮动

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>父模板</title>
  6. <link rel="stylesheet" href="{{ url_for('static',filename='css/bootstrap.css') }}">
  7. </head>
  8. <body>
  9. <form class="navbar-form navbar-left" role="search">
  10. <div class="form-group">
  11. <input type="text" class="form-control" placeholder="Search">
  12. </div>
  13. <button type="submit" class="btn btn-default">Submit</button>
  14. </form>
  15. <div style=" visibility:hidden;display:block;font-size:0;clear:both;
  16. height:50px"></div>
  17. {% block main %}
  18. <p>父模板中main中原有的内容</p>
  19. {% endblock %}
  20. <br>
  21. <br>
  22. <br>
  23. {% block demo %}
  24. <p>demo中原有的内容</p>
  25. {% endblock %}
  26. <div style=" visibility:hidden;display:block;font-size:0;clear:both;
  27. height:0"></div>
  28. <nav aria-label="Page navigation">
  29. <ul class="pagination">
  30. <li>
  31. <a href="#" aria-label="Previous">
  32. <span aria-hidden="true">&laquo;</span>
  33. </a>
  34. </li>
  35. <li><a href="#">1</a></li>
  36. <li><a href="#">2</a></li>
  37. <li><a href="#">3</a></li>
  38. <li><a href="#">4</a></li>
  39. <li><a href="#">5</a></li>
  40. <li>
  41. <a href="#" aria-label="Next">
  42. <span aria-hidden="true">&raquo;</span>
  43. </a>
  44. </li>
  45. </ul>
  46. </nav>
  47. </body>
  48. </html>

detail.html

  1. {% extends 'base.html' %}
  2. {% block demo %}
  3. <p>子模板中重写demo的内容</p>
  4. {% endblock %}
  5. {% block main %}
  6. {{ super() }} {# 保留基模板中本block的代码 #}
  7. {{ self.demo() }} {# 调用demo block的代码 #}
  8. <p>子模板中重写main的内容 </p>
  9. {% endblock %}

app.py 注意:app.config.update(TEMPLATES_AUTO_RELOAD=True)语句用于每次都重新加载模板文件

  1. from flask import Flask, render_template
  2. app = Flask(__name__)
  3. app.config.update(TEMPLATES_AUTO_RELOAD=True)
  4. @app.route('/')
  5. def hello_world():
  6. return render_template('base.html')
  7. @app.route('/demo/')
  8. def demo():
  9. return render_template('detail.html')
  10. if __name__ == '__main__':
  11. app.run()

子模板运行效果
04-01 模板 - 图18

3 闪现

3.1 在模板中获取闪现信息

Flask 提供了一个非常简单的方法来使用闪现系统向用户反馈信息。闪现系统使得在一个请求结束的时候记录一个信息,然后在且仅仅在下一个请求中访问这个数据,强调flask闪现是基于flask内置的session的,利用浏览器的session缓存闪现信息。所以必须设置secret_key

3.1.1 简单的在模板中实现获取闪现信息

实例:
server.py

  1. from flask import Flask, flash, redirect, render_template, \
  2. request, url_for
  3. app = Flask(__name__)
  4. app.secret_key = 'some_secret'
  5. @app.route('/')
  6. def index():
  7. return render_template('index.html')
  8. @app.route('/login', methods=['GET', 'POST'])
  9. def login():
  10. error = None
  11. if request.method == 'POST':
  12. if request.form['username'] != 'admin' or \
  13. request.form['password'] != '123':
  14. error = '登录失败'
  15. else:
  16. flash('恭喜您登录成功')
  17. return redirect(url_for('index'))
  18. return render_template('login.html', error=error)
  19. if __name__ == "__main__":
  20. app.run()

注意:这个 flash() 就可以实现在下一次请求时候,将括号内的信息做一个缓存。不要忘记设置secret_key
这里是 index.html 模板:

  1. {% with messages = get_flashed_messages() %} # 获取所有的闪现信息返回一个列表
  2. {% if messages %}
  3. <ul class=flashes>
  4. {% for message in messages %}
  5. <li>{{ message }}</li>
  6. {% endfor %}
  7. </ul>
  8. {% endif %}
  9. {% endwith %}
  10. <h1>主页</h1>
  11. <p>跳转到登录页面<a href="{{ url_for('login') }}">登录?</a>

注意:{% with messages = get_flashed_messages() %} # 获取所有的闪现信息返回一个列表
这里是login.html 模板

  1. <h1>登录页面</h1>
  2. {% if error %}
  3. <p class=error><strong>Error:</strong> {{ error }}
  4. {% endif %}
  5. <form action="" method=post>
  6. 用户名:
  7. <input type=text name=username>
  8. 密码:
  9. <input type=password name=password>
  10. <p><input type=submit value=Login></p>
  11. </form>

04-01 模板 - 图19
简单的在模板中实现获取闪现信息小结:

  1. 设置闪现内容:flash('恭喜您登录成功')
  2. 模板取出闪现内容:{% with messages = get_flashed_messages() %}

3.1.2 模板中的分类闪现

当闪现一个消息时,是可以提供一个分类的。未指定分类时默认的分类为 'message' 。 可以使用分类来提供给用户更好的反馈,可以给用户更精准的提示信息体验。
要使用一个自定义的分类,只要使用 flash() 函数的第二个参数:

  1. flash('恭喜您登录成功',"status")
  2. flash('您的账户名为admin',"username")

在使用get_flashed_messages()时候需要传入with_categories=true便可以渲染出来类别

  1. {% with messages = get_flashed_messages(with_categories=true) %}
  2. {% if messages %}
  3. <ul class=flashes>
  4. {% for category, message in messages %}
  5. <li class="{{ category }}">{{ category }}:{{ message }}</li>
  6. {% endfor %}
  7. </ul>
  8. {% endif %}
  9. {% endwith %}

04-01 模板 - 图20

3.1.3 模板中过滤闪现消息

同样要使用一个自定义的分类,只要使用 flash() 函数的第二个参数:

  1. flash('恭喜您登录成功',"status")
  2. flash('您的账户名为admin',"username")

在使用get_flashed_messages()时候需要传入category_filter=["username"]便可根据类别取出闪现信息。中括号内可以传入的值就是类别,可以传入多个。

  1. {% with messages = get_flashed_messages(category_filter=["username"]) %}
  2. {% if messages %}
  3. <ul>
  4. {%- for message in messages %}
  5. <li>{{ message }}</li>
  6. {% endfor -%}
  7. </ul>
  8. </div>
  9. {% endif %}
  10. {% endwith %}

04-01 模板 - 图21
小结:

  1. 分类设置闪现内容:flash('恭喜您登录成功',"status")
  2. flash('您的账户名为admin',"username")
  3. 模板取值: % with messages = get_flashed_messages(category_filter=["username"]) %}
  4. {% if messages %}
  5. <ul>
  6. {%- for message in messages %}

3.2 在视图中获取闪现信息

3.2.1 简单的在是视图中获取闪现信息

  1. -设置: flash('xxx')
  2. -取值:get_flashed_message() # 注意这个不同于模板取值,这个是从flask中导入的
  3. -注意:在视图中获取闪现信息不必非得是两次连续的请求,只要保证是第一次取相应的闪现信息,就可以取得到。

实例:

  1. from flask import Flask, request, flash, get_flashed_messages
  2. import os
  3. app = Flask(__name__)
  4. app.secret_key = os.urandom(4)
  5. app.debug = True
  6. @app.route('/login/')
  7. def login():
  8. if request.args.get('name') == 'rocky':
  9. return 'ok'
  10. flash('第一条闪现信息:用户名不是rocky填写的是{}'.format(request.args.get('name')))
  11. # flash('第二条闪现信息:用户名不是rocky填写的是{}'.format(request.args.get('name')))
  12. return 'error,设置了闪现'
  13. @app.route('/get_flash/')
  14. def get_flash():
  15. #get_flashed_messages()是一个列表列表可以取出闪现信息,该条闪现信息只要被取出就会删除掉。
  16. return '闪现的信息是{}'.format(get_flashed_messages())
  17. @app.route('/demo/')
  18. def demo():
  19. return 'demo'
  20. if __name__ == '__main__':
  21. app.run()

(1) 会触发设置闪现内容
04-01 模板 - 图22
(2)取出闪现内容
04-01 模板 - 图23
(3)再次取出闪现内容,发现闪现内容取出一次后就为空了
04-01 模板 - 图24
小结:

  • get_flashed_messages()是一个列表,该列表可以取出闪现信息,该条闪现信息只要被取出就会删除掉。

3.2.2 在视图中实现分类获取闪现信息。

  1. -设置:flash('用户名错误', "username_error")
  2. flash('用户密码错误', "password_error") # 第二个参数为闪现信息的分类。
  3. -取所有闪现信息的类别和闪现内容:get_flashed_messages(with_categories=True)
  4. -针对分类过滤取值:get_flashed_messages(category_filter=['username_error'])
  5. # 中括号内可以写多个分类。
  6. -注意:如果flash()没有传入第二个参数进行分类,默认分类是 'message'

实例1

  1. @app.route('/login/')
  2. def login():
  3. if request.args.get('name') == 'rocky':
  4. return 'ok'
  5. flash('用户名错误', category="username_error")
  6. flash('用户密码错误', "password_error")
  7. return 'error,设置了闪现'
  8. @app.route('/get_flash/')
  9. def get_flash():
  10. return '闪现的信息是{}'.format(get_flashed_messages(with_categories=True))

把所有的闪现类别和闪现信息返回。
04-01 模板 - 图25
实例2

  1. @app.route('/login/')
  2. def login():
  3. if request.args.get('name') == 'rocky':
  4. return 'ok'
  5. flash('用户名错误', category="username_error")
  6. flash('用户密码错误', "password_error")
  7. return 'error,设置了闪现'
  8. @app.route('/get_flash/')
  9. def get_flash():
  10. return '闪现的信息是{}'.format(get_flashed_messages(category_filter=['username_error']))

返回页面只显示了 "username_error"的分类内容。
04-01 模板 - 图26