0217 flask框架介绍

Flask框架

1. flask

3大web框架

1 django
    django是一个同步框架,orm,模板都是自己写的,如果你要快速开发,一个比较大的项目就用django。相当于御姐,什么都有,你不需要做任何调教,你想要都有,你想不到它也有。

2 flask
    flask也是一个同步框架,orm不是自己写的,jinja2模板,flask小项目,能不能做大项目?能,它相当于一个纯情妹子,什么都不懂,但是你教它以后,它就什么都懂了,它需要你自己去做开发。

3 torando
    torando它是异步框架,都没有。

简介

Flask 属于微框架(micro-framework)这一类别,我们可以使用Python语言快速实现一个网站或Web服务。微架构通常是很小的不依赖于外部库的框架。这既有优点也有缺点,优点是框架很轻量,更新时依赖少,缺点是你不得不自己做更多的工作,或通过添加插件增加自己的依赖列表。flask默认的模板渲染引擎是janjia2

flask作为一个轻量级框架,它里面有好多扩展包需要下载,比较麻烦,而且有的时候flask需要在虚拟环境下运行,但是他的优点还是有滴 ,只要是用过Django的人,都会觉得flask是真的 '轻'

Flask自由、灵活,可扩展性强,能结合最流行最强大的Python库
入门简单,即便没有多少web开发经验,也能很快做出网站
非常适用于小型网站
非常适用于开发web服务的API
开发大型网站无压力,但代码架构需要自己设计,开发成本取决于开发者的能力和经验
各方面性能均等于或优于Django
Django自带的或第三方的好评如潮的功能,Flask上总会找到与之类似第三方库
Flask灵活开发,Python高手基本都会喜欢Flask,但对Django却可能褒贬不一
Flask与关系型数据库的配合使用不弱于Django,而其与NoSQL数据库的配合远远优于Django

flask里面的技术点有很多,比如cookie ,session ,过滤器 ,四个钩子,werkzeug和jinja2 ,蓝图.等等.
 
先来说说这四个钩子,很多人会问:钩子?什么钩子,肯定一脸懵逼,对于钩子我的理解是: 可以把flask四种钩子看作是修饰器,我们在后端可以进行调用做相关的操作.使用钩子函数时,我们需要借助flask的全局变量g.g作为中间变量,在钩子函数和视图函数中间传递数据.我们先引入全局变量g

安装

pip install flask

创建项目

Flask不同于Django,不会提供任何自动的操作,所以需要手动创建项目目录,需要手动创建启动项目的管理文件

例如,创建项目目录flaskdemo,在目录中创建manage.py。在pycharm中打开项目并指定上面创建的虚拟环境

1.导入flask类
form flask import Flask

2.实例化一个flask对象
app = Flask(__name__)  
	# __name__是模块的名称或者包的名称
    # 作用: 根据这个参数确定flask应用的路径, 从而快速查找模板和html文件的默认路径;也可以说这里的app就是一个程序实例,客户端(一般是浏览器)将请求发送给服务端Web服务器,Web服务器再把请求发给Flask实例。

3.基本路由
@app.route('/')
def index():
    return 'Hello World'
	# @app.route(’/’): 告诉Flask哪个url才能出发对应的函数,又称为路由;对应定义了一个视图函数,也就是返回给用户浏览器显示的内容; 即路由所对应的程序称为视图函数(view function),即上面的index()函数

4.运行flask应用
if __name__ == '__main__':
    app.run()
    # app.run()运行应用,启动服务器,可以指定ip和端口‘0.0.0.0’ 所有的IP都可以访问到 例如:app.run('0.0.0.0', 9000)

配置类

#加载项目配置
#配置类
class Config(object)
    DEBUG = True
    SECRET_KEY = "aaabbbbbddddeeeeb"

app.config.from_object(Config)


#指定服务器IP和端口
app.run(host="0.0.0.0",port=5000,debug = True)

2. flask的四剑客

1.直接返回字符串

直接return字符串显示数据

2.render_template

返回html页面,类似于Django的render

要创建一个templates文件夹,把所有的HTML文件都放在其中

初始化app.py设置文件中参数templates_folder参数指定了文件夹的目录

3.redirect

跳转页面
与Django中的redirect一致

4.jsonify

就是将可以序列化的数据转化为json返回

代码

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

' a test module '

__author__ = 'Fwzzz'


from flask import Flask,render_template,redirect,jsonify
app = Flask(__name__)


# 字符串
@app.route('/')
def index():
	return 'ok'

#HTML页面
@app.route('/index')
def index1():
    return render_template('index.html')

#跳转
@app.route('/login')
def index2():
    return redirect('/')

#json数据
@app.route('/json')
def json11():
    data = {'name':'tank','love':'piao'}
    return jsonify(data)


if __name__ == '__main__':
    app.run()

3. flask的配置文件

方式1 (app.属性)

只能配置两项(在文件中书写)

app.debug = True
app.secert_key = 'abc'

方式2 (app.config字典)

全大写属性
app.config['DEBUG'] = True

方式3 (以文件的形式进行配置)app.config.from_pyfile()

另外新建一个文件,文件中改变

app.config.from_pyfile('文件路径.py')
	
设置新建文件setting:
	DEBUG = False

方式4 (以类的形式 推荐使用)app.config.from_object()

新建文件,文件中使用类的方式进行设置,可以方便调试,Flask配置的随时切换


app.config.from_object('类的文件.类名.py')


设置文件:
    
	class Config:
		DEBUG = False
        
     # 产品配置
     class ProductConfig(Config):
        pass
    
    # 测试文件使用
     class TestConfig(Config):
        pass

4. flask的路由

路由的本质

#指定访问路径为demo1
@app.route('/demo1')
def demo1():
    return 'demo1'

本质就是
@app.route('/detail/<int:nid>',methods=['GET'],endpoint='detail')



"""
1. decorator = app.route('/',methods=['GET','POST'],endpoint='n1')
    def route(self, rule, **options):
        # app对象
        # rule= /
        # options = {methods=['GET','POST'],endpoint='n1'}
        def decorator(f):
            endpoint = options.pop('endpoint', None)
            self.add_url_rule(rule, endpoint, f, **options)
            return f
        return decorator
2. @decorator
    decorator(index)
"""
#同理
def login():
    return '登录'
app.add_url_rule('/login', 'n2', login, methods=['GET',"POST"])
#与django路由类似
#django与flask路由:flask路由基于装饰器,本质是基于:add_url_rule
#add_url_rule 源码中,endpoint如果为空,endpoint = _endpoint_from_view_func(view_func),最终取view_func.__name__(函数名)

url构建与反向解析(url_for)

from flask import Flask, request, url_for

app=Flask(__name__)

@app.route('/welcome/<string:user>')
def welcome(user):
    return user +'用户,欢迎光临'

@app.route('/path/')
def path():
    print(request.headers)

    #查看默认url地址的请求方法
    print(request.method)
    #url_for:根据函数名,反向生成url地址
    print('用户正在访问url地址:%s' %(url_for(endpoint='welcome',user='Merry')))
    return '用户正在访问url地址:%s' %(url_for(endpoint='welcome',user='Merry'))

app.run()

通过 request类,可以得到其头部信息或者访问模式,是 get 或者 post 等

app.add_url_rule参数

@app.route和app.add_url_rule参数:

rule
	URL规则
    
view_func
	视图函数名称
    
defaults = None
	默认值, 当URL中无参数,函数需要参数时,使用defaults = {'k': 'v'}为函数提供参数
    
endpoint = None, 
	名称,用于反向生成URL,即: url_for('名称')
    
methods = None, 
	允许的请求方式,如:["GET", "POST"]

strict_slashes = None
	#对URL最后的 / 符号是否严格要求

redirect_to = None, 
	#重定向到指定地址

代码


    '''
        @app.route('/index', strict_slashes=False)
        #访问http://www.xx.com/index/ 或http://www.xx.com/index均可
        @app.route('/index', strict_slashes=True)
        #仅访问http://www.xx.com/index
    '''
#重定向到指定地址
redirect_to = None, 
    '''
        @app.route('/index/<int:nid>', redirect_to='/home/<nid>')
    '''

#子域名访问
subdomain = None, 
    '''
    #C:WindowsSystem32driversetchosts
    127.0.0.1       www.liuqingzheng.com
    127.0.0.1       admin.liuqingzheng.com
    127.0.0.1       buy.liuqingzheng.com
    
    from flask import Flask, views, url_for
    app = Flask(import_name=__name__)
    app.config['SERVER_NAME'] = 'liuqingzheng.com:5000'
    @app.route("/", subdomain="admin")
    def static_index():
        """Flask supports static subdomains
        This is available at static.your-domain.tld"""
        return "static.your-domain.tld"
    #可以传入任意的字符串,如传入的字符串为aa,显示为 aa.liuqingzheng.com
    @app.route("/dynamic", subdomain="<username>")
    def username_index(username):
        """Dynamic subdomains are also supported
        Try going to user1.your-domain.tld/dynamic"""
        return username + ".your-domain.tld"
    if __name__ == '__main__':
        app.run()
        
    访问:
    http://www.liuqingzheng.com:5000/dynamic
    http://admin.liuqingzheng.com:5000/dynamic
    http://buy.liuqingzheng.com:5000/dynamic
    '''

路由传参(两种方式)

不限制类型

# 路由传递参数[没有限定类型]
@app.route('/user/<user_id>')
def user_info(user_id):
    return 'hello %s' % user_id

限制类型的有名分组

# 路由传递参数[限定数据类型]
@app.route('/user/<int:user_id>')
def user_info(user_id):
    return 'hello %d' % user_id
    
# 默认转换器
DEFAULT_CONVERTERS = {
    'default':          UnicodeConverter,
    'string':           UnicodeConverter,
    'any':              AnyConverter,
    'path':             PathConverter,
    'int':              IntegerConverter,
    'float':            FloatConverter,
    'uuid':             UUIDConverter,
}

正则匹配路由

在 web 开发中,可能会出现限制用户访问规则的场景,那么这个时候就需要用到正则匹配,根据自己的规则去限定请求参数再进行访问

具体实现步骤为:

  • 导入转换器基类:在 Flask 中,所有的路由的匹配规则都是使用转换器对象进行记录
  • 自定义转换器:自定义类继承于转换器基类
  • 添加转换器到默认的转换器字典中
  • 使用自定义转换器实现自定义匹配规则

代码

> 导入转换器基类

from werkzeug.routing import BaseConverter

> 自定义转换器

1 # 自定义正则转换器
2 from werkzeug.routing import BaseConverter
3 class RegexConverter(BaseConverter):
4     def __init__(self,url_map,*args):
5         super(RegexConverter, self).__init__(url_map)
6         # 正则参数
7         self.regex = args[0]

> 添加转换器到默认的转换器字典中,并指定转换器使用时名字为: re

1 # 将自定义转换器添加到转换器字典中,并指定转换器使用时名字为: re
2 app.url_map.converters['re'] = RegexConverter

  > 使用转换器去实现自定义匹配规则

    >> 当前此处定义的规则是 :手机号

1 # 正则匹配路由
2 @app.route("/login/<re('1d{10}'):mobile>")
3 def login(mobile):
4     return mobile

系统转换器

DEFAULT_CONVERTERS = {
    'default':          UnicodeConverter,
    'path':             PathConverter,
    'string':           UnicodeConverter,
    'any':              AnyConverter,
    'int':              IntegerConverter,
    'float':            FloatConverter,
    'uuid':             UUIDConverter,
}

系统自带的转换器具体使用方式在每种转换器的注释代码中有写,请留意每种转换器初始化的参数。

from flask import Flask
# 新增一个配置文件,在配置文件中设置配置信息
from config import Config
from flask import request
# from collections import OrderedDict  # 有序字典

app = Flask(__name__)

# 调用app.config加载配置
app.config.from_object(Config)


from werkzeug.routing import BaseConverter

class RegexConverter(BaseConverter):
    def __init__(self,url_map,*args):
        super(RegexConverter, self).__init__(url_map)
        # 正则参数
        self.regex = args[0]

# converter["路由转换器名称"] = 实现路由转换功能的自定义类
app.url_map.converters['re'] = RegexConverter
# 绑定路由
@app.route("/")
def index():
    return "hello flask"


# 默认情况下,路由使用的就是关键字参数,也叫"命名路由"
# router(路由地址, http请求方式 )
@app.route("/list/<int:page>/<string:content>",methods=["GET","POST"])
def mylist(content,page):
    return "第%s页<br>内容:%s" % (page,content)

# 正则匹配路由
@app.route("/login/<re('1d{10}'):mobile>")
def login(mobile):
    return mobile

5. flask的CBV

如果继承的是views.View必须重写def dispatch_request(self)

from  flask import Flask,views,url_for
app = Flask(__name__)

#如果继承的是views.View必须实现 def dispatch_request(self):
class IndexView(views.View):
    methods = ["POST","GET"]
    #decorators= ["装饰器的函数对象",]
    def dispatch_request(self):
        return "index"

#app.add_url_rule("/index",view_func=view)(View中as_view函数中嵌套的view)
app.add_url_rule("/index",view_func=IndexView.as_view(name="index"))
	# 固定写法: app.add_url_rule('路由',view_func=类.as_view(name='反向解析用'))

继承views.MethodView

直接继承了views.MethodView

class LoginView(views.MethodView):
    def post(self):
        return "post"
    def get(self):
        print(url_for("123"))
        return  "get"

app.add_url_rule("/login",view_func=LoginView.as_view(name="login"))

if __name__ == '__main__':
    app.run()

6.模板渲染

直接在render_template返回时添加`变量名=值`,前段页面进行接收

return  render_template("index1.html",num=a,user_dic = list_info ,htm=html,ff=ff)

代码

from flask import Flask,render_template,Markup
app = Flask(__name__)


# 定义一个函数,可以返回给前端
def ff(arg,b):
    return  Markup(arg+b)


@app.route("/")
def index():
    a = 123
    list_info ={
        1:{"name":"tank","long":160,"颜值":50},
        2:{"name":"jason","long":170,"颜值":60},
        3:{"name":"饼","long":190,"颜值":80}
    }
    html ="<h1> jason is sb</h1>"
    return  render_template("index1.html",num=a,user_dic = list_info ,htm=html,ff=ff)
	# 这里将函数传到前段页面以及参数html,可以在前段页面进行处理


if __name__ == '__main__':
    app.run()

index1.html

渲染变量

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>用户列表</h1>
    <table>
        {% for k,v in user_dict.items() %}
        <tr>
            <td>{{k}}</td>
            <td>{{v.name}}</td>
            <td>{{v['name']}}</td>
            <td>{{v.get('name')}}</td>
            <td><a href="/detail/{{k}}">查看详细</a></td>
        </tr>
        {% endfor %}
    </table>
</body>
</html>

变量的循环

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>用户列表</h1>
    <table>
        {% for k,v in user_dict.items() %}
        <tr>
            <td>{{k}}</td>
            <td>{{v.name}}</td>
            <td>{{v['name']}}</td>
            <td>{{v.get('name')}}</td>
            <td><a href="/detail/{{k}}">查看详细</a></td>
        </tr>
        {% endfor %}
    </table>
</body>
</html>

逻辑判断

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>用户列表</h1>
    <table>
        {% if name %}
          <h1>Hello {{ name }}!</h1>
        {% else %}
          <h1>Hello World!</h1>
        {% endif %}
    </table>
</body>
</html>

传递函数(可以加括号)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    {{ff('六五')}}
    {{ff('六五')|safe}}

</body>
</html>

传递html文字

使用Markup  等价于Django的mark_safe
extends,include一模一样

from flask import Flask,render_template,Markup,jsonify,make_response
app = Flask(__name__)

def func1(arg):
    return Markup("<input type='text' value='%s' />" %(arg,))
@app.route('/')
def index():
    return render_template('index.html',ff = func1)

if __name__ == '__main__':
    app.run()

html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

    {{ff('六五')}}
    {{ff('六五')|safe}}

</body>
</html>

7.请求与响应

请求参数

# 请求相关信息
        # request.method  提交的方法
        # request.args  get请求提及的数据
        # request.form   post请求提交的数据
        # request.values  post和get提交的数据总和
        # request.cookies  客户端所带的cookie
        # request.headers  请求头
        # request.path     不带域名,请求路径
        # request.full_path  不带域名,带参数的请求路径
        # request.script_root  
        # request.url           带域名带参数的请求路径
        # request.base_url      带域名请求路径
        # request.url_root      域名
        # request.host_url      域名
        # request.host          127.0.0.1:500
        # request.files
        # obj = request.files['the_file_name']
        # obj.save('/var/www/uploads/' + secure_filename(f.filename))

响应参数

# 响应相关信息
        # return "字符串"
        # return render_template('html模板路径',**{})
        # return redirect('/index.html')
        #return jsonify({'k1':'v1'})

        # response = make_response(render_template('index.html'))
        # response是flask.wrappers.Response类型
        # response.delete_cookie('key')
        # response.set_cookie('key', 'value')
        # response.headers['X-Something'] = 'A value'
        # return response
        return "内容"

代码

   from flask import Flask
    from flask import request
    from flask import render_template
    from flask import redirect
    from flask import make_response

    app = Flask(__name__)


    @app.route('/login.html', methods=['GET', "POST"])
    def login():

        # 请求相关信息
        # request.method  提交的方法
        # request.args  get请求提及的数据
        # request.form   post请求提交的数据
        # request.values  post和get提交的数据总和
        # request.cookies  客户端所带的cookie
        # request.headers  请求头
        # request.path     不带域名,请求路径
        # request.full_path  不带域名,带参数的请求路径
        # request.script_root  
        # request.url           带域名带参数的请求路径
        # request.base_url      带域名请求路径
        # request.url_root      域名
        # request.host_url      域名
        # request.host          127.0.0.1:500
        # request.files
        # obj = request.files['the_file_name']
        # obj.save('/var/www/uploads/' + secure_filename(f.filename))

        # 响应相关信息
        # return "字符串"
        # return render_template('html模板路径',**{})
        # return redirect('/index.html')
        #return jsonify({'k1':'v1'})

        # response = make_response(render_template('index.html'))
        # response是flask.wrappers.Response类型
        # response.delete_cookie('key')
        # response.set_cookie('key', 'value')
        # response.headers['X-Something'] = 'A value'
        # return response
        return "内容"

    if __name__ == '__main__':
        app.run()
cookie:存放在客户端的键值对 
session:存放在客户端的键值对 
token:存放在客户端,通过算法来校验

设置cookie

make_response实例化得到response对象然后set_cookie

设置cookie需要通过flask的Response响应对象来进行设置,由flask内部提供了一个make_response函数给我们可以快速创建响应对象

from flask imoprt Flask,make_response
@app.route('/set_cookie')
def set_cookie():
    resp = make_response('this is to set cookie')
    resp.set_cookie('username', 'xiaoming', max_age=3600)
    # max_age 为cookie有效期,单位为秒
    return resp

获取cookie

from flask import Flask,request
@app.route('/get_cookie')
def resp_cookie():
    resp = request.cookies.get('username')
    return resp

删除cookie

response.delete_cookie("name")

9. session

对于敏感、重要的信息,建议要存储在服务器端,不能存储在浏览器中,如用户名、余额、等级、验证码等信息

在服务器端进行状态保持的方案就是Session

注意: Session依赖于Cookie,而且flask中使用session,需要配置SECRET_KEY选项,否则报错.

app.secret_key="asdas" # 值随便(保证session不可预测)

代码

from  flask import Flask,session
app = Flask(__name__)
app.secret_key = "aihsdasnd"
app.config['SESSION_COOKIE_NAME']="sbd"

@app.route("/")
def index():
    session['name'] = "jason"

    return "ok"

@app.route("/login")
def login():
    print(session["name"])
    return  "ojbk"

if __name__ == '__main__':
    app.run()

特点

#在django中发什么三件事
	1,生成一个随机的字符串 
	2 往数据库存 
	3 写入cookie返回浏览器
	
#在flask中他没有数据库,但session是怎样实现的?
    # 生成一个密钥写入这个cookie,然后下次请求的时候,通过这个cookie解密,然后赋值给session
    #我们通过app.session_interface来查看

#flask的sessoin存的步骤
    # 第一步将session的这个字典做加密得到val,
    # 第二步将 配置文件中SESSION_COOKIE_NAME作为key,
    # 第三步,设置cookies,以上述的key,val,做键值
    
#flask的session取的步骤
    # 第一步,获取cookies中键为SESSION_COOKIE_NAME的值,
    # 第二步: 将第一步获取的值做解密操作得到真的val值

设置session

设置:session['username'] = 'xxx'


from flask import session
@app.route('/set_session')
def set_session():
    session['username'] = 'xiaoming'
    return 'ok!'

获取session

@app.route('/get_session')
def get_session():
    return session.get('session的文件名')
    # 也可以直接使用session['session名']获取

删除session

删除:session.pop('username', None)

源码流程

key, 键
value='', 值
max_age=None, 超时时间 cookie需要延续的时间(以秒为单位)如果参数是 None`` ,这个cookie会延续到浏览器关闭为止
expires=None, 超时时间(IE requires expires, so set it if hasn't been already.)
path='/', Cookie生效的路径,/ 表示根路径,特殊的:根路径的cookie可以被任何url的页面访问,浏览器只会把cookie回传给带有该路径的页面,这样可以避免将cookie传给站点中的其他的应用。
domain=None, Cookie生效的域名 你可用这个参数来构造一个跨站cookie。如, domain=".example.com"所构造的cookie对下面这些站点都是可读的:www.example.com 、 www2.example.com 和an.other.sub.domain.example.com 。如果该参数设置为 None ,cookie只能由设置它的站点读取
secure=False, 浏览器将通过HTTPS来回传cookie
httponly=False 只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)


---------------------------------------------------------

session源码的执行流程

    -save_seesion
        -响应的时候,把session中的值加密序列化放大到了cookie中,返回到浏览器中
    -open_session
        -请求来了,从cookie中取出值,反解,生成session对象,以后再视图函数中直接用sessoin就可以了。

10 闪现(message)

使用

-设置: flash('aaa')
	flash('超时错误!',category='x1') # category对设置的信息分类
	
-取值:get_flashed_message()
	data=get_flashed_messages(category_filter='x1')# 根据信息分类来获取值

特点

1 没有设置,取是不会报错的,返回一个空列表

2 设置了就可以在任何一个视图函数中去取

3 取了一次就没有了。(但是在同一次请求中可以取多次)

实例

-假设在a页面操作出错,跳转到b页面,在b页面显示a页面的错误信息

from flask import Flask,flash,get_flashed_messages,request,redirect

app = Flask(__name__)
app.secret_key = 'asdfasdf'


@app.route('/index')
def index():
    # 从某个地方获取设置过的所有值,并清除。
    val = request.args.get('v')
    if val == 'oldboy':
        return 'Hello World!'
    flash('超时错误',category="x1")
    return "ssdsdsdfsd"
    # return redirect('/error')


@app.route('/error')
def error():
    """
    展示错误信息
    :return:
    如果get_flashed_messages(with_category=True)
    """
    data = get_flashed_messages(category_filter=['x1'])
    if data:
        msg = data[0]
    else:
        msg = "..."
    return "错误信息:%s" %(msg,)

if __name__ == '__main__':
    app.run()

一:闪现flash基本用法

# -*- coding: utf-8 -*-
# @Author : Felix Wang
# @time   : 2018/7/5 9:34

from flask import Flask, flash, get_flashed_messages

app = Flask(__name__)
app.debug = True
app.secret_key = 'dddddddd'


# 闪现flash基本用法,本质是通过session来实现的


@app.route('/get')
def get():
    # 从某个地方获取设置过的所有值,并清除
    data = get_flashed_messages()
    print(data)
    return 'hello world'


@app.route('/set')
def set():
    # 向某个地方设置一个值
    flash('哈哈哈')
    return 'hello world'


if __name__ == '__main__':
    app.run()

二:闪现实例-显示错误信息

# -*- coding: utf-8 -*-
# @Author : Felix Wang
# @time   : 2018/7/5 9:34

from flask import Flask, flash, get_flashed_messages,request,redirect

app = Flask(__name__)
app.debug = True
app.secret_key = 'dddddddd'


# 闪现基于session来实现的
# 应用:对临时数据操作;如:显示错误信息


@app.route('/index')
def index():

    val=request.args.get('v')
    if val=='a':
        return 'Hello World!'
    flash('超时错误!',category='x1') # category对设置的信息分类
    return redirect('/error')


@app.route('/error')
def error():
    data=get_flashed_messages(category_filter='x1')# 根据信息分类来获取值
    if data:
        msg=data[0]
    else:
        msg=''
    return '错误信息,{}'.format(msg)


if __name__ == '__main__':
    app.run()
原文地址:https://www.cnblogs.com/fwzzz/p/12459046.html