返回总目录页

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就是和外界进行沟通的地方

 

posted @ 2022-10-01 20:48  马昌伟  阅读(114)  评论(0编辑  收藏  举报
博主链接地址:https://www.cnblogs.com/machangwei-8/