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 返回给前端
'''
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")
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(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 一旦有请求取出,再去别的的请求中取,就没了,无论有没有分类,都没了
请求扩展
# 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()