Flask四

发布时间 2023-11-17 21:08:28作者: 别管鱼油我了

session源码

1、app.session_interface默认是某个类的对象,以后全局对象session,就是SecureCookieSessionInterface()的对象

2、请求来了,会执行这个对象的open_session方法

3、请求走了,会执行这个对象的save_session方法

4、读源码:

app.run()---->run_simple(地址, 端口, self可调用对象)--->self 是 app

请求来了,就会执行self可调用对象(),app(),对象加(),触发类的__call__

请求来了,就会执行flask类的__call__,self.wsgi_app(environ, start_response)

  • environ : 一个 dict、用于存放请求相关的数据
  • start_response : 一个 function、用于发送响应头部
def wsgi_app(self, environ: dict, start_response: t.Callable) -> t.Any:
        ctx = self.request_context(environ)
        try:
            try:
                ctx.push()
                response = self.full_dispatch_request()
            except Exception as e:
                error = e
                response = self.handle_exception(e)
            except:  # noqa: B001
                error = sys.exc_info()[1]
                raise
            return response(environ, start_response)
        finally:
            if "werkzeug.debug.preserve_context" in environ:
                environ["werkzeug.debug.preserve_context"](_cv_app.get())
                environ["werkzeug.debug.preserve_context"](_cv_request.get())

            if error is not None and self.should_ignore_error(error):
                error = None

            ctx.pop(error)

5 ctx.push()--->有如下代码

if self.session is None: # 请求刚来,是空的
    #session_interface 就是SecureCookieSessionInterface类的对象
    self.session = session_interface.open_session(self.app, self.request)

    if self.session is None:
        self.session = session_interface.make_null_session(self.app)

6  SecureCookieSessionInterface类的open_session

from flask.sessions import SecureCookieSessionInterface

open_session步骤:

1、会去cookie中取出session对应的三段式的字符串

2、解密,校验签名,把这个数据放到session对象中

save_session步骤:

1、从session取出数据

2、加密,签名,放到cookie中

3、返回给前端

save_session

1、视图函数中,咱们session[name]=qx

2、请求走了就会触发save_session

3、触发save_session时:把session中的数据,加密签名得到三段字符串,放到cookie中,放到浏览器中

def save_session(
    self, app: Flask, session: SessionMixin, response: Response
) -> None:
    name = self.get_cookie_name(app)
    domain = self.get_cookie_domain(app)
    path = self.get_cookie_path(app)
    secure = self.get_cookie_secure(app)
    samesite = self.get_cookie_samesite(app)
    httponly = self.get_cookie_httponly(app)

    # Add a "Vary: Cookie" header if the session was accessed at all.
    if session.accessed:
        response.vary.add("Cookie")

        # If the session is modified to be empty, remove the cookie.
        # If the session is empty, return without setting the cookie.
        if not session:
            if session.modified:
                response.delete_cookie(
                    name,
                    domain=domain,
                    path=path,
                    secure=secure,
                    samesite=samesite,
                    httponly=httponly,
                )
                response.vary.add("Cookie")

                return

            if not self.should_set_cookie(app, session):
                return

            expires = self.get_expiration_time(app, session)
            # 加密,签名---放到cookie中
            val = self.get_signing_serializer(app).dumps(dict(session))  # type: ignore
            response.set_cookie(
                name,
                val,  # type: ignore
                expires=expires,
                httponly=httponly,
                domain=domain,
                path=path,
                secure=secure,
                samesite=samesite,
            )
            response.vary.add("Cookie")

open_session

1、请求来了,request中带着cookie(也可能没有)

2、根据session这个key,取出value,如果有,就是我们当时的三段

3、字典=s.loads(value),把内容验签,解密出来,转成了字典

4、把这个字典转到了session对象中

5、以后视图函数中,session[name]就能取到当时你放的name

def open_session(self, app: Flask, request: Request) -> SecureCookieSession | None:
    s = self.get_signing_serializer(app)
    if s is None:
        return None
    # val 就是那三段
    val = request.cookies.get(self.get_cookie_name(app))
    if not val:
        # 如果没有带cookie,造个空session,返回
        return self.session_class()
    max_age = int(app.permanent_session_lifetime.total_seconds())
    try:
        data = s.loads(val, max_age=max_age)
        # 解密,校验签名---》把这个数据--》放到 session对象中
        return self.session_class(data)
    except BadSignature:
        return self.session_class()

django session的控制


from django.contrib.sessions.middleware import SessionMiddleware
 

闪现

flash翻译过来的

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

以后遇到,在当次请求有数据要存,下次请求还能取出来,这样就可以使用闪现

设置闪现:

  1、普通使用:通过闪现,放进去,取一次,就没了

    flash  #放到闪现中,加密放到了cookie中

  2、分类,以分类放入

    flash(s, category='xxx')

    flash('xxx', category='yyy')

取闪现:

  1、普通取,全取出来,从闪现中取出来

    err=get_flashed_message()[0]   (这是一个列表,,所以要索引取值)

  2、根据分类取

  err = get_flashed_messages(category_filter=['xxx'])[0]

总结:

1、设置flash,可以按分类设置

2、去flash,在当次请求,可以取出多次,都是在的

3、一旦有请求取出,再去别的请求取,就没了,无论有没有分类,都没了

 

请求扩展

django中中间件,对所有请求拦截

flask中使用请求扩展实现

    django       flask
  process_request----》before_request
  process_response--->after_request

就是中django中间件

  请求头中判断有没有user-agent做反扒

  响应头中加入跨域的

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

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


@app.before_request
def before():
    # 做统一处理,处理校验失败,不让他继续往后走了
    '''
    return  None---->继续走下一个请求扩展
    return 新手四件套
    '''
    print('来了')


@app.before_request
def before2():
    # 做统一处理,处理校验失败,不让他继续往后走了
    '''
    return  None---->继续走下一个请求扩展
    return 新手四件套
    '''
    print('来了222')
    # return '不行了'


@app.after_request
def after(response):
    print('走了')
    # return response
    
    return make_response('你看到我了')


@app.route('/')
def home():
    print('home')
    return 'home'


@app.route('/order')
def order():
    return 'order'


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