5-flask-session源码(save_session和open_session)、flask闪现、 flask请求扩展

1 session源码
1.1 save_session
1.2 open_session
1.3 django session的控制

2 闪现
3 请求扩展

1 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)
    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 返回给前端

1.1 save_session

'''
1 视图函数中,咱们  session[name]=lqz
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")

1.2 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()

1.3 django session的控制

from django.contrib.sessions.middleware import SessionMiddleware


Django 中的 Session 控制主要涉及到用户会话的管理。会话是指在用户与 web 服务器之间的一段时间内,服务器可以存储关于用户的信息的机制。Django 使用 Session 来存储用户的会话信息。

以下是 Django 中关于 Session 控制的一些建议和常用操作:

1. **启用 Session Middleware:** 确保 `django.contrib.sessions.middleware.SessionMiddleware` 被添加到 `MIDDLEWARE` 配置中。
2. 这是用于处理 session 的中间件。

3. **配置 Session 引擎:** Django 支持多种 Session 引擎,包括数据库引擎、缓存引擎等。
4. 在 `settings.py` 文件中,通过设置 `SESSION_ENGINE` 来选择使用的引擎。例如:
    # settings.py
    SESSION_ENGINE = 'django.contrib.sessions.backends.db'


5. **Session 的过期时间:** 可以通过 `SESSION_COOKIE_AGE` 设置 Session 的过期时间,以秒为单位。默认是 1209600 秒(2 周)。
    # settings.py
    SESSION_COOKIE_AGE = 1209600  # 2 weeks in seconds


6. **Session 的存储位置:** 如果选择使用数据库引擎,可以通过 `SESSION_SAVE_EVERY_REQUEST` 设置是否在每个请求中保存 Session 数据。
    # settings.py
    SESSION_SAVE_EVERY_REQUEST = True


7. **Session 的清理:** Django 提供了 `clearsessions` 管理命令,用于清理过期的 Session 数据。
    python manage.py clearsessions


8. **Session 的使用:** 在视图中,你可以通过 `request.session` 来访问和设置 Session 数据。
    # views.py
    def set_session(request):
        request.session['username'] = 'john'
        return HttpResponse("Session data set.")

    def get_session(request):
        username = request.session.get('username', 'Guest')
        return HttpResponse(f"Hello, {username}.")


9. **Session 的删除:** 你可以通过 `del request.session['key']` 或者 `request.session.pop('key', None)` 来删除 Session 中的某个键。

Django 的 Session 控制提供了一种灵活和可定制的方式来管理用户的会话信息,
可以根据项目的需求进行相应的配置。

2 闪现

# flash 翻译过来的
# 假设在a页面操作出错,跳转到b页面,在b页面显示a页面的错误信息

# 以后遇到,在当次请求有数据要存,下次请求还能取出来,就可以使用闪现
### 设置闪现
    # 1 普通使用 :通过闪现---》放进去,取一次,就没了
    	# flash(s)  # 放到闪现中了,加密放到了cookie总
    # 2 分类,以分类放入
        flash(s, category='xxx')  
        flash('xxx', category='yyy') 
        
### 取闪现
    # 1 普通取,全取出来 从闪现中取出来
    # err = get_flashed_messages()[0]
    # 2 根据分类取
    err = get_flashed_messages(category_filter=['xxx'])[0]
    
    
    
# 总结:
	1 设置flash,可以按分类设置
    2 去flash,在当前请求中,可以取出多次,都是在的
    3 一旦有请求取出,再去别的的请求中取,就没了,无论有没有分类,都没了

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()

你可能感兴趣的:(flask,flask,session,flask闪现,flask请求扩展)