flask3之CBV和session
flask的CBV
CBV书写案例
from flask import Flask app=Flask(__name__) #FBA @app.route("/") def index(): return "200 OK" #CBV from flask import views class Login(views.MethodView): def get(self): return "I am Get" def post(self): pass def mcwZidingyi(self): pass app.add_url_rule("/login", endpoint="my_login", view_func=Login.as_view(name="LoginLogin"), methods=["GET","POST"] ) if __name__ == '__main__': app.run("0.0.0.0",9527)
CBV详解
FBV视图函数的路由是route方法,而route方法实际上是(app对象)调用add_url_rule()方法。所以CBV添加路由的方式可以直接使用对象点add_url_rule()。第一个参数是路径,第二个参数是别名,第三个是类中的某个函数(方法) 后面的是字典类参数接收
所以CBV视图类写法如下:
导入views,定义类并继承views.MethodView。(MethodView又继承MethodViewType, View)。
定义get,post等方法,里面写对应方法的业务逻辑,并返回响应
视图类添加url路由。flask对象点添加url规则。参数中指定请求路径,endpoint别名,指定视图函数,视图函数是对应的类点as_view,里面有个name参数必填,起个名字
这样就写好了,在浏览器上访问
还可以换行并指定请求参数
def add_url_rule( self, rule, endpoint=None, view_func=None, provide_automatic_options=None, **options ):
CBV使用befor_request不影响(中间件效果,装饰器效果)
这个decoraters是不需要的,多写了
这个方法的执行跟视图函数还是视图类没有关系,是一样的。它们只跟请求有关系
from flask import Flask app=Flask(__name__) # @app.before_request # def is_login(): # print("是否登录,进入视图函数前") # @app.after_request # def login_ok(res): # return res def zhuanshiqi(func): def inner(): print("前") res=func() print("前") return res return inner from flask import views class Login(views.MethodView): decoraters=[zhuanshiqi] def get(self): print("已经登录了,进入了视图函数") return "I am Get" def post(self): pass def mcwZidingyi(self): pass app.add_url_rule("/login", endpoint="my_login", view_func=Login.as_view(name="LoginLogin"), methods=["GET","POST"] ) if __name__ == '__main__': app.run("0.0.0.0",9527)
flask总结
Flask 轻量级的框架 轻,三方支持全 Django 原生组件全,好 pip install flask # 1.1.1 1.Flask 启动 增加路由和视图 2.Flask 中的 Response 1.HTTPResponse - return "HTTPResponse" 返回字符串 2.render - 返回模板页面 3.redirect - 跳转 重定向 response location: url Flask特殊封装 4.send_file("文件路径") - 打开并返回文件内容 自动识别文件类型 Content-Type:text/plan 5.jsonify({k:v}) - 返回标准的JSON字符串 Content-Type:application/json return d # == jsonify(d) # Sanic - Sonic 索尼克 蓝刺猬 ==== Flask Web ////// async def login() 3.Flask 中的 Request from flask import request request.method # 请求方式 # print(request.args.get("id")) # 获取 URL 中的请求参数 /login?id=1 字典 # print(request.args.to_dict()) # 将获取的数据转化为字典 # print(request.form.get("u")) # FormData中的数据 POST 请求提交 form == args # print(request.form.to_dict()) request.json # 请求头中带有 Content-Type:application/json request.data # 请求头中不带有 Form or FormData 保存请求体中的原始信息 b"" request.url # 自己试 request.path # 自己试 request.host # 自己试 request.host_url # 自己试 print(request.files) # file_storage 直接保存文件 file = request.files.get("my_file") # file file_storage filename = file.filename print(filename) file.save("当前文件名或者文件路径.png") 4.Flask 中的原生 Session Session : from flask import session 密钥:secret_key 用于 Session 序列化字符串 app.secret_key = "#$%^&*(^%$#$%^&*%$%^&*^%$%^*^TYUH^TYUGYUGHTYUG" 使用 session: session["key"] = "value" 开启session session.get("key") session 存在哪儿 交由客户端保管机制 5.Flask 中的路由 methods # 允许进入当前视图函数的请求方式 ** methods=["get","post","PUT","delete"] # HTTP 8 种 ** endpoint # Mapping 对应关系 视图函数 - 路由 必须保证唯一 defaults # 默认参数 redirect_to # 永久重定向 301 or 308 strict_slashes # 是否严格遵循路由匹配规则 ** 动态参数路由: @app.route("/home/<string:username>") # 默认动态参数 为string def home(username): return f"123 200 Ok!{username}" 6.Flask 初始化配置 app = Flask(__name__) template_folder # 模板存放路径 static_folder # 静态文件存放路径 默认值 static static_url_path # 静态文件访问路径 f"/{static_folder}" 7.Flask 对象配置 app.config app.debug = True # 自动重启 透传错误信息 Log级别较低 Debug 级别 app.config["DEBUG"] = True app.config["SECRET_KEY"] = "%^(&^%&(*^%&*^&Y" app.config["PERMANENT_SESSION_LIFETIME"] = 30 app.config["SESSION_COOKIE_NAME"] = "I am Not Session" app.config["JSONIFY_MIMETYPE"] = "alex/DSB" # jsonify Content-Type中的值 app.config # 非常重要 8.Flask 的蓝图 蓝图 - 不能被Run的Flask 对象 from flask import Flask app = Flask(__name__) from flask import Blueprint user_bp = Blueprint("蓝图标识",__name__) @user_bp.route("/user_bp") def user(): return "user_bp" app.register_blueprint("user_bp") 9.Flask 的特殊装饰器 @app.before_request # 在请求进入视图函数之前,执行 @app.after_request # 在请求结束视图函数之后,响应返回客户端之前 正常情况: be1 - be2 - be3 - vf - af3 - af2 - af1 异常情况: be1 - be2 - af3 - af2 - af1 @app.errorhandler(HttpErrorCode) # 重定义错误返回信息 HttpErrorCode [4xx,5xx] @app.errorhandler(404) def error404(errorMessage): print(errorMessage) return "当前页面不存在正在跳转.....10s后自动跳转" # Flask 5种响应方式 # return redirect("") 10.Flask 中的 CBV -- restAPI from flask import views from flask.views import MethodView class Login(MethodView): def get(self): return render_template("login.html") def post(self): if request.form.get("username") == "alex": return redirect("/index") def alexdsb(self): # views 中 追加 "alexdsb" 请求方式 pass app.add_url_rule("/login",view_func=Login.as_view(name="login")) 11.Flask 请求上下文
flask-session
安装flask-session第三方包。
flask原生session
我们写个flask程序,一个设置session的视图函数,一个查看session的视图函数。
当我们前端访问设置session时,报错了,这是因为没有设置密钥
我们在app配置中添加一下密钥。然后在浏览器再次访问设置session的url,发现正常响应数据了。浏览器检查元素,查看应用下面的session,可以看到这条设置的session了。这是flask原生的session。
研究flask-session第三方组件如何对接flask(源码分析及使用)
比如将session写入redis,
需要导入flask_session
from flask_session import Session
需要配置session类型,redis连接对象,初始化app。其它的不用变,还是按照flask的session方式去set和get就行
app.config["SESSION_TYPE"]="redis"
app.config["SESSION_REDIS"]=Redis(host="10.0.0.12",port=6379,db=10,password='haohaio')
Session(app)
from flask import Flask,request,session from flask_session import Session from redis import Redis app=Flask(__name__) # app.secret_key="sfwesj19y48327504274927*T^6DD$%4%%^D&" app.config["SESSION_TYPE"]="redis" app.config["SESSION_REDIS"]=Redis(host="10.0.0.12",port=6379,db=10,password='haohaio') Session(app) @app.route("/sets") def sets(): session["key"]="machangwei" return "Set OK" @app.route("/gets") def gets(): return session.get("key") if __name__ == '__main__': app.run()
我们接下来要看的是flask-session,这是第三方组件。它能更改session的存放位置
我们来看一下flask-session的源码:
我们导入flask——session,看看这个session给我们做了哪些操作
因为我们使用的这个地方组件,需要用到app的配置,所以这个类初始化一个对象的时候,需要将app对象传进去,开辟一个空间复制原来的app,app不是空,那么我们给这个新的app初始化一下,
初始化就是为了设置一下接口。self.app是自己的app,不是原来的app,不是同一个内存空间。而下面初始化app里面的app是原来的app,可以看上面,调用初始化app的时候,传递的是原来的app,而不是新生的self.app,也就是初始化app里面对app对象的操作,会直接影响到全局的app对象,因为这里传的是原来初始化的Flask对象app.
我们可以看一下,app里面确实是有这个配置的
而我们这里的app还是原来的app,这里就是需要对原来的app做修改了
我们点击进去看一下,默认的接口是cookiesession的接口
再点击去看,这是将session保存在cookie里面,从名字上看出来
flask是根据这个session接口来确定session的保存位置
再次回到第三方组件,session里面初始化app的操作,就是将原来的app接口,改写掉
现在重新定义session接口,这找接口就找我们这里定义的接口了,看下这个session接口配置是怎么定义的
将app传进来了,我们定义一个自己的配置字典,这个配置字典是复制了app的配置,注意这里传进来的app还是原来的app。然后我们对自己的config做操作,设置默认值。点设置默认值方法的原理是:如果config中有这个键,那么config就不理会,还是原来的值;如果config中没有这个键,那么我就设置这里后面的为默认值,设置这么一个键值对。
我们自己重新定义的额,也复制到这个新的config里面了
下面的设置了一个redis的默认值
下面还有设置了将session存放到文件当中的方法
app config的初始化变量都是在app 默认config下面定义的
它还可以通过sqlalchemy来存放session.
下面是对session类型做判断,前面设置默认配置的时候,也就是设置session类型的时候是设置了字符串null。所以下面这些判断目前匹配不上
前面的判断不成立,只能走else了,将session接口定义为是空的session接口函数的调用。flask-session的session获取session接口方法,返回这个新的session接口。
我们获取session接口,返回的空session接口到初始化app中的app里的session接口了。这里是原来的app,也就是原来的app接口变成了这个空session接口对象了
我们接下来看看空session接口继承了谁
这和我们的flask里面的session一样,都是继承session接口
再看看这个session接口是啥,是flask里面的session接口
而第三方组件的session接口继承的是flask session接口
在第三方组件session里面的flask session接口,点击一下,一下子就跳到了flask session里面了。也就是第三方组件还是继承的flask session接口
也就是我们的第三方组件返回的空session接口也就是等价于flask里面的安全cookie session接口,默认的还是跟flask的默认一样,是保存在cookie里面。而前面的判断,是看有没有其他接口,有的话走其它的接口,没有匹配到的话就走flask原来默认的接口,相当于不改变flask原来的功能上,新增了其它功能。新增了很多可选项
再回到获取接口的方法前头,定义session类型这里。定义session类型,设置默认值,如果原来的配置里面没有session类型,设置为null,走else默认的session类型接口。但是我们可以定义app的配置。
那么我们在原来的app配置下加上类型使用redis。再次走到session类型这里之后,发现有值redis,那么我们新的config里面的session类型保持不变,还是redis,下面返回接口要走的判断是redis接口的判断了
获取接口方法里面,往下就该判断了,判断会走redis这里了。redis这里就是将session接口定义为redis session接口,里面放的一些配置,是前面设置的默认配置,查看了 下就session_redis是None没有值。
我们点击这个redis session接口类,可以看到,它是none的时候实例化一个redis连接对象。这里没有主机在哪里,那实例化连接的是本机,显然我们是需要填写主机在哪里的
我们不传session_redis参数的时候,默认是none,它默认实例化一个本机的redis.我们不要本机的redis连接对象,需要连接的是其它远程redis,那么我们重写这个参数就行,
我们在前面传递一个配置,是这个远程连接的redis对象。这下下面的获得session接口就能实现使用redis对象返回的接口了
如下,我们已经将添加了配置了,其它的没有改变,设置session还是使用小写的从flask中导入的那个
我们重新方法设置session的url。发现添加的值,是一小段字符串了,而不是加密后的session了
我们去redis中查看数据,之前是没有数据的,现在有了数据了,两个是一致的,存在浏览器的是session id,不再是session值了。
我们get 一下session id,可以看到session的值了。key 和value到包含在字符串里面了
我们在浏览器上执行get看一下。从session中获取到这个key键的值。我们的session id还在浏览器中保留着。
我们把浏览器上的session id删除再次get访问,浏览器这里又生成了一个session id,不过我们从这个session中获取不到key值报错了。
这个生成的session id也是写入到redis里面了的。我们get访问的时候用的这个session id。然后去redis中的session里面找key,没有数据,响应的session get key是没有的应该是none把,前端报错了。
我们再次执行set sesstion,还是用的这个没有数据的session ,但是访问结束之后,在这个session中添加了数据,并不是重新生成一个session。
如下,还是两个session,没增加,但是刚刚没有数据的session已经有了数据了。有了数据之后,前端再次get,拿着这个session id匹配到session数据,从数据里面找key,就能找到它对应的值了。
我们写 第三方组件的初始化需要在app配置之后,不能放在前面,因为我们是基于app配置的。这里重点不是如何在flask中使用flask-session,而是如何用flask-session如何对接我们的flask。flask组件大都是基于config来写的。用你现在的config替换掉你之前的config,或者是拿你现在的config指向另外一个地方。这个app config就是和外界进行沟通的地方
当我们使用了这个组件之后,这里不设置密钥也是可以的,可能是组件帮我们加了默认的了把
总结:
这里重点不是如何在flask中使用flask-session,而是如何用flask-session如何对接我们的flask。flask组件大都是基于config来写的。用你现在的config替换掉你之前的config,或者是拿你现在的config指向另外一个地方。这个app config就是和外界进行沟通的地方