目录
1.HTTP的会话控制
1.什么是会话控制?
会话的开始是在用户通过浏览器第一次访问服务端网站开始.
所谓的会话控制,就是在客户端浏览器和服务端网站之间,进行多次http请求响应之间,记录、跟踪和识别用户的信息而已。
2.会话控制出现的原因
无状态:指一次用户请求时,浏览器、服务器无法知道之前这个用户做过什么,每次请求都是一次新的请求。
无状态原因:浏览器与服务器是使用 socket 套接字进行通信的,服务器将请求结果返回给浏览器之后,会关闭当前的 socket 连接,而且服务器也会在处理页面完毕之后销毁页面对象。
3.会话控制的应用场景
实现状态保持主要有两种类型:
-
在客户端存储信息使用
url
,Cookie
,token令牌[jwt.csrf,oauth]
-
在服务器端存储信息使用
2.使用场景: 登录状态,浏览历史,网站足迹,购物车 [不登录也可以使用购物车]
3.Cookie是存储在浏览器中的一段纯文本信息,建议不要存储敏感信息如密码,因为电脑上的浏览器可能被其它人使用
4.Cookie基于域名安全,不同域名的Cookie是不能互相访问的
如访问luffy.com时向浏览器中写了Cookie信息,使用同一浏览器访问baidu.com时,无法访问到luffy.com写的Cookie信息
5.浏览器的同源策略针对cookie也有限制作用.
6.当浏览器请求某网站时,会将本网站下所有Cookie信息提交给服务器,所以在request中可以读取Cookie信息
1.设置cookie
设置cookie需要通过flask的Response响应对象来进行设置,由响应对象会提供了方法set_cookie给我们可以快速设置cookie信息。
@app.route("/set_cookie") def set_cookie(): """设置cookie""" response = make_response(ok) # 格式:response.set_cookie(key="变量名",value="变量值",max_age="有效时间/秒") response.set_cookie(username",xiaoming) 如果cookie没有设置过期时间,则默认过期为会话结束过期""" cookie在客户端中保存时,用一个站点下同变量名的cookie会覆盖 response.set_cookie(age100) return response
2.获取cookie
@app.route(/get_cookie get_cookie(): 获取cookie""" print(request.cookies) print(request.cookies.get()) )) 打印效果: {'username': 'xiaoming'} return ""
3.删除cookie
@app.route(/del_cookie del_cookie(): 删除cookie 把对应名称的cookie设置为过期时间(0s),则可以实现删除cookie response.set_cookie("",0) return response
3.Session
2.在服务器端进行状态保持的方案就是Session
3.Session依赖于Cookie,session的ID一般默认通过cookie来保存到客户端。
4.flask中的session需要加密,所以使用session之前必须配置SECRET_KEY选项,否则报错.
5.session的有效期默认是会话期,会话结束了,session就废弃了。
6.如果将来希望session的生命周期延长,可以通过修改cookie中的sessionID来完成配置。
1.设置session
from flask import Flask,make_response,request,session app = Flask(__name__) class Config(): flask中的session需要加密,所以使用session之前必须配置SECRET_KEY选项,否则报错. SECRET_KEY = 123456asdadad DEBUG = True app.config.from_object(Config) @app.route(/set_session set_session(): 设置session与cookie不同,session支持python基本数据类型作为值 session["] = xiaohuihuiinfo"] = { ":11sex:True,} " if __name__ == '__main__': app.run(debug=True)
2.获取session
@app.route(/get_session get_session(): 获取sessionprint( session.get() ) "
3.删除session
@app.route(/del_session del_session(): 删除sessiontry: del session[] session.clear() # 删除所有 exceptpass "
Tip:如何查看当前flask默认支持的所有配置项
Config(): SECRET_KEY = True app.config.from_object(Config) 查看当前flask默认支持的所有配置项 (app.config) 下面是flask默认支持的所有配置项 <Config { 'DEBUG': False,'TESTING': False,'PROPAGATE_EXCEPTIONS': None,'PRESERVE_CONTEXT_ON_EXCEPTION': None,'SECRET_KEY': None,'PERMANENT_SESSION_LIFETIME': datetime.timedelta(31),'USE_X_SENDFILE': False,'LOGGER_NAME': '__main__','LOGGER_HANDLER_POLICY': 'always','SERVER_NAME': None,'APPLICATION_ROOT': None,'SESSION_COOKIE_NAME': 'session','SESSION_COOKIE_DOMAIN': None,'SESSION_COOKIE_PATH': None,'SESSION_COOKIE_HTTPONLY': True,'SESSION_COOKIE_SECURE': False,'SESSION_REFRESH_EACH_REQUEST': True,'MAX_CONTENT_LENGTH': None,'SEND_FILE_MAX_AGE_DEFAULT': datetime.timedelta(0,43200),'TRAP_BAD_REQUEST_ERRORS': False,'TRAP_HTTP_EXCEPTIONS': False,'EXPLAIN_TEMPLATE_LOADING': False,'PREFERRED_URL_SCHEME': 'http','JSON_AS_ASCII': True,'JSON_SORT_KEYS': True,'JSONIFY_PRETTYPRINT_REGULAR': True,'JSONIFY_MIMETYPE': 'application/json','TEMPLATES_AUTO_RELOAD': None """
4.请求钩子
-
在请求开始时,建立数据库连接;
-
在请求开始时,根据需求进行权限校验;
-
在请求结束时,指定数据的交互格式;
为了让每个视图函数避免编写重复功能的代码,Flask提供了通用设置的功能,即请求钩子。
请求钩子是通过装饰器的形式实现,Flask支持如下四种请求钩子:
-
before_first_request
-
在处理第一个请求前执行[项目初始化时的钩子]
-
-
before_request
-
after_request
-
teardown_request:
) @app.before_first_request first_request(): print(1. 项目启动以后,首次被请求时,会自动执行[项目全局初始化工作]) @app.before_request before_request(): 2. 每次客户端请求时,都会自动执行,常用于记录访问日志,进行权限判断,身份识别,访问限流...) @app.after_request after_request(response): 4. 每次视图执行以后,会自动执行 after_request执行以后,必须要返回结果给客户端!! return response @app.teardown_request teardown_request(exc): 5. after_request完成以后,如果有发生异常,在关闭DEBUG模式的情况下可以接受异常对象,进行异常的记录,异常通知(exc) @app.route(/ set_session(): 3. 视图执行了.......: app.run(debug=False)
第1次请求时打印:
1. 项目启动以后,首次被请求时,会自动执行[项目全局初始化工作]
2. 每次客户端请求时,都会自动执行,常用于记录访问日志,进行权限判断,身份识别,访问限流...
3. 视图执行了.......
4. 每次视图执行以后,会自动执行
5. after_request完成以后,如果有发生异常,在关闭DEBUG模式的情况下可以接受异常对象,进行异常的记录,异常通知
None
第2次请求时打印:
2. 每次客户端请求时,都会自动执行,常用于记录访问日志,进行权限判断,身份识别,访问限流...
3. 视图执行了.......
4. 每次视图执行以后,会自动执行
5. after_request完成以后,如果有发生异常,在关闭DEBUG模式的情况下可以接受异常对象,进行异常的记录,异常通知
None
@L_403_11@5.捕获错误
flask中内置了app.errorhander提供给我们捕获异常,实现一些在业务发生错误时的自定义处理。
1. 通过http状态码捕获异常信息
2. 通过异常类进行异常捕获
@app.errorhandler(500 internal_server_error(e): 服务器搬家了'
2.捕获指定系统异常类
@app.errorhandler(ZeroDivisionError) zero_division_error(e): 除数不能为0'
3.也可以捕获自定义异常类
Flask app = Flask() 加载配置""" Config(): DEBUG = True app.config.from_object(Config) 捕获系统异常或者自定义异常 APIError(Exception): pass @app.route( index(): raise APIError(api接口调用参数有误!个人中心,视图执行了!! @app.errorhandler(APIError) error_apierror(e): 错误: %s" % e : app.run(host=localhost6.上下文:context
Flask中上下文对象:相当于一个容器,保存了 Flask 程序运行过程中的一些信息[变量、函数、类与对象等信息]。
Flask中有两种上下文,请求上下文(request context)和应用上下文(application context)。
request 指的是每次
http
请求发生时,WSGI server
(比如gunicorn)调用Flask.__call__()
之后,在Flask
对象内部创建的Request
对象;application 表示用于响应WSGI请求的应用本身,request 表示每次http请求;
application的生命周期大于request,一个application存活期间,可能发生多次http请求,所以,也就会有多个
1.请求上下文(request context)
在 flask 中,可以直接在视图函数中使用 request 这个对象进行获取相关数据,而 request 就是请求上下文的对象,保存了当前本次请求的相关数据,请求上下文对象有:request、session
request
session
注意!!!!:请求上下文提供的变量/属性/方法/函数/类与对象,只能在视图中或者被视图调用的地方使用
2.应用上下文(application context)
应用上下文对象有:current_app,g
1.current_app
初始化 app = Flask(import_name= 声明和加载配置 True app.config.from_object(Config) 编写路由视图 @app.route(rule= 注意!!!!:应用上下文提供给我们使用的变量,也是只能在视图或者被视图调用的地方进行使用, 但是应用上下文的所有数据来源于于app,每个视图中的应用上下文基本一样 print(current_app.config) 获取当前项目的所有配置信息 print(current_app.url_map) 获取当前项目的所有路由信息 <h1>hello world!</h1>" : 运行flask app.run(host=0.0.0.0")2.g变量
g 作为 flask 程序全局的一个临时变量,充当者中间媒介的作用,我们可以通过它传递一些数据,g 保存的是当前请求的全局变量,不同的请求会有不同的全局变量,通过不同的thread id区别
True app.config.from_object(Config) @app.before_request before_request(): g.name = root get_two_func(): name = g.name g.name=%s name) get_one_func(): get_two_func() 请求上下文提供的变量/属性/方法/函数/类与对象,只能在视图中或者被视图调用的地方使用 请求上下文里面信息来源于每次客户端的请求,所以每个视图中请求上下文的信息都不一样 print(session) 应用上下文提供给我们使用的变量,也是只能在视图或者被视图调用的地方进行使用, 获取当前项目的所有路由信息 get_one_func() ")3.关于请求上下文和应用上下文的总结
由flask提供了2种不同的上下文对象给我们开发者获取项目或者客户端的信息
这些对象不需要我们进行实例化,由flask内部创建的
1. 请求上下文: request,session
2. 应用上下文: current_app,g不管是请求上下文或者应用上下文都只能使用在视图范围内或者能被视图调用的地方
如果是视图以外地方使用,则会报错:
RuntimeError: Working outside of application context.解决方案:
with app.app_context():
print(g)''' 请求上下文提供的变量/属性/方法/函数/类与对象,只能在视图中或者被视图调用的地方使用 请求上下文里面信息来源于每次客户端的请求,所以每个视图中请求上下文的信息都不一样 ''' 应用上下文提供给我们使用的变量,也是只能在视图或者被视图调用的地方进行使用, 但是应用上下文的所有数据来源于于app,每个视图中的应用上下文基本一样 '''7.Flask-Script
这个模块的作用可以让我们通过终端来控制flask项目的运行,类似于django的manage.py
安装命令:
pip install flask-script1.启动终端脚本运行项目
Flask from flask_script Manager app = Flask( 注册终端脚本工具到app中 manager = Manager(app) @app.route( 注意,这里不是app对象 manager.run() 端口和域名不写,默认为127.0.0.1:5000 # python run.py runserver 通过-h设置启动域名,-p设置启动端口 python run.py runserver -h127.0.0.1 -p88882.自定义终端命令
如果我们想自定义终端命令,必须要遵从以下三点
1. 引入Command命令基类
2. 创建命令类必须直接或间接继承Command,并在内部实现run方法,同时如果有自定义的其他参数,则必须实现__init__
3. 使用flask_script应用对象manage.add_command对命令类进行注册,并设置调用终端别名。import Manager,Command,Option 1.引入command命令基类 app = Flask( True app.config.from_object(Config) 基于flask_script创建自定义终端命令class HelloCommand(Command): 2.1 创建命令类必须直接或间接继承Command 命令相关的注释 option_list = [ Option(--name-n名称),Option(--num-m数量def run(self,name,num): 2.2 在自定义终端命令内部实现run方法 name=%s name) (num) 命令执行了!!! Manager(app) manager.add_command(hello 3.使用flask_script应用对象manage.add_command对命令类进行注册,并设置调用终端别名。 @app.route(: manager.run() 运行该程序 python run.py hello -n=hahaha -m=qiqiqi运行结果:
@H_237_1403@
3.自定义脚手架命令
1.引入Command命令基类 app = Flask( True app.config.from_object(Config) manager = Manager(app) os class BluePrintCommand(Command): 2.1 创建命令类直接或间接继承Command option_list =蓝图名称) ] 2.2 在命令类内部实现run方法 if name is None: 蓝图名称不能为空!) return if not os.path.isdir(name): os.mkdir(name) open(%s/views.py" % name,1)">w) open(%s/models.py) with open(%s/urls.py) as f: f.write(from . import views urlpatterns = [ ] ) manager.add_command(blue 3.使用应用对象.add_command对命令类进行注册,并设置调用终端别名 : manager.run() 运行程序 python run.py blue -n=users运行结果: