【Flask教程09】状态保持
一、状态保持
- 因为 http 是一种无状态协议,浏览器请求服务器是无状态的。
- 无状态:指一次用户请求时,浏览器、服务器无法知道之前这个用户做过什么,每次请求都是一次新的请求。
- 无状态原因:浏览器与服务器是使用 socket 套接字进行通信的,服务器将请求结果返回给浏览器之后,会关闭当前的 socket 连接,而且服务器也会在处理页面完毕之后销毁页面对象。
- 有时需要保持下来用户浏览的状态,比如用户是否登录过,浏览过哪些商品等
- 实现状态保持主要有两种方式:
- 在客户端存储信息使用
Cookie
- 在服务器端存储信息使用
Session
- 在客户端存储信息使用
无状态协议:
- 协议对于事务处理没有记忆能力
- 对同一个 url 请求没有上下文关系
- 每次的请求都是独立的,它的执行情况和结果与前面的请求和之后的请求是无直接关系的,它不会受前面的请求应答情况直接影响,也不会直接影响后面的请求应答情况
- 服务器中没有保存客户端的状态,客户端必须每次带上自己的状态去请求服务器
- 人生若只如初见
状态举例:
- 有状态:
- A:你今天中午吃的啥?
- B:吃的大盘鸡。
- A:味道怎么样呀?
- B:还不错,挺好吃的。
- 无状态:
- A:你今天中午吃的啥?
- B:吃的大盘鸡。
- A:味道怎么样呀?
- B:???啊?啥?啥味道怎么样?
- 所以需要cookie这种东西:
- A:你今天中午吃的啥?
- B:吃的大盘鸡。
- A:你今天中午吃的大盘鸡味道怎么样呀?
- B:还不错,挺好吃的。
二、Cookie
- Cookie:指某些网站为了辨别用户身份、进行会话跟踪而储存在用户本地的数据(通常经过加密)。
- 复数形式Cookies。
- Cookie最早是网景公司的前雇员Lou Montulli在1993年3月的发明。
- Cookie是由服务器端生成,发送给客户端浏览器,浏览器会将Cookie的key/value保存,下次请求同一网站时就发送该Cookie给服务器(前提是浏览器设置为启用cookie)。
- Cookie的key/value可以由服务器端自己定义。
- 应用:
- 最典型的应用是判定注册用户是否已经登录网站,用户可能会得到提示,是否在下一次进入此网站时保留用户信息以便简化登录手续,这些都是Cookie的功用。
- 网站的广告推送,经常遇到访问某个网站时,会弹出小窗口,展示我们曾经在购物网站上看过的商品信息。
- 购物车,用户可能会在一段时间内在同一家网站的不同页面中选择不同的商品,这些信息都会写入Cookie,以便在最后付款时提取信息。
-
提示:
- Cookie是存储在浏览器中的一段纯文本信息,建议不要存储敏感信息如密码,因为电脑上的浏览器可能被其它人使用
- Cookie基于域名安全,不同域名的Cookie是不能互相访问的
- 如访问cnblogs.com时向浏览器中写了Cookie信息,使用同一浏览器访问baidu.com时,无法访问到cnblogs.com写的Cookie信息
- 浏览器的同源策略
-
当浏览器请求某网站时,会将本网站下所有Cookie信息提交给服务器,所以在request中可以读取Cookie信息
-
(1)设置cookie
from flask imoprt Flask,make_response @app.route('/cookie') def set_cookie(): resp = make_response('this is to set cookie') resp.set_cookie('username', 'cnblogs') return resp
- 设置过期时间
@app.route('/cookie') def set_cookie(): response = make_response('hello world') response.set_cookie('username', 'cnblogs', max_age=3600) return response
(2)获取cookie
from flask import Flask,request #获取cookie @app.route('/request') def resp_cookie(): resp = request.cookies.get('username') return resp
三、Session
- 对于敏感、重要的信息,建议要存储在服务器端,不能存储在浏览器中,如用户名、余额、等级、验证码等信息
- 在服务器端进行状态保持的方案就是
Session
- Session依赖于Cookie
session数据的获取
session:请求上下文对象,用于处理http请求中的一些数据内容
@app.route('/index1') def index1(): session['username'] = 'cnblogs' return redirect(url_for('index')) @app.route('/') def index(): return session.get('username')
设置secret_key方式1:
Flask 使用消息闪烁(flash)报错:The session is unavailable because no secret key was set
解决方法:设置Flask实例的SECTET_KEY属性。代码如下:
from flask import Flask app = Flask(__name__)app.config['SECRET_KEY'] = '123456'
设置secret_key方式2:
记得设置secret_key: app.secret_key = 'cnblogs' secret_key的作用:https://segmentfault.com/q/1010000007295395
四、上下文
上下文:相当于一个容器,保存了 Flask 程序运行过程中的一些信息。
Flask中有两种上下文,请求上下文和应用上下文
(1)请求上下文(request context)
思考:在视图函数中,如何取到当前请求的相关数据?比如:请求地址,请求方式,cookie等等
在 flask 中,可以直接在视图函数中使用 request 这个对象进行获取相关数据,而 request 就是请求上下文的对象,保存了当前本次请求的相关数据,请求上下文对象有:request、session
- request
- 封装了HTTP请求的内容,针对的是http请求。举例:user = request.args.get('user'),获取的是get请求的参数。
- session
- 用来记录请求会话中的信息,针对的是用户信息。举例:session['name'] = user.id,可以记录用户信息。还可以通过session.get('name')获取用户信息。
(2)应用上下文(application context)
它的字面意思是 应用上下文,但它不是一直存在的,它只是request context 中的一个对 app 的代理(人),所谓local proxy。它的作用主要是帮助 request 获取当前的应用,它是伴 request 而生,随 request 而灭的。
应用上下文对象有:current_app,g
current_app
应用程序上下文,用于存储应用程序中的变量,可以通过current_app.name打印当前app的名称,也可以在current_app中存储一些变量,例如:
- 应用的启动脚本是哪个文件,启动时指定了哪些参数
- 加载了哪些配置文件,导入了哪些配置
- 连了哪个数据库
- 有哪些public的工具类、常量
- 应用跑再哪个机器上,IP多少,内存多大
current_app.name current_app.test_value='value'
g变量
g 作为 flask 程序全局的一个临时变量,充当者中间媒介的作用,我们可以通过它传递一些数据,g 保存的是当前请求的全局变量,不同的请求会有不同的全局变量,通过不同的thread id区别
g.name='abc'
注意:不同的请求,会有不同的全局变量
两者区别:
- 请求上下文:保存了客户端和服务器交互的数据
- 应用上下文:flask 应用程序运行过程中,保存的一些配置信息,比如程序名、数据库连接、应用信息等
上下文中的对象只能在指定上下文中使用,超出范围不能使用 请求上下文和应用上下文原理实现:https://segmentfault.com/a/1190000004223296