补充一下

request是在哪里产生的:

class RequestContext(object):
# app就是flask对象
self.app = app
if request is None:
request = app.request_class(environ) # Request(environ) 处理request
self.request = request # 就是这里没错了
self.url_adapter = app.create_url_adapter(self.request)
self.flashes = None
self.session = None

请求流程

session的存取过程

session的取值过程位于上图的此部分

Flask实例的open_session方法首先是取了session_interface的值--一个类(SecureCookieSessionInterface)的对象,调用了他的open_session方法,将取出来的值赋予了ctx.session,存储到了Local实例中

session的存值过程

则是调用了session_interface代表的类实例的save_session方法但是这里存在一个问题:

class SecureCookieSessionInterface(SessionInterface):
session_class = SecureCookieSession
def open_session(self, app, request):
return self.session_class() # ctx的session就是这个类的实例
# 父类中的此方法,我给直接写到这里了,如果此函数返回False,save_session不会设置cookie
def should_set_cookie(self, app, session):
if session.modified:
# 如果session.modified为True就说明session修改过了,为什么说修改过了,看下面
return True
save_each = app.config['SESSION_REFRESH_EACH_REQUEST']
# session.permanent在SessionMixin类中
return save_each and session.permanent def save_session(self, app, session, response):
# 保存session时会根据session的modified来判断将不将session写进cookie中,下面简写
if not self.should_set_cookie(app, session):
return # session的类
class SecureCookieSession(CallbackDict, SessionMixin):
def __init__(self, initial=None):
def on_update(self):
self.modified = True
CallbackDict.__init__(self, initial, on_update)
self.modified = False # 默认是False class CallbackDict(UpdateDictMixin, dict):
def __init__(self, initial=None, on_update=None):
dict.__init__(self, initial or ())
self.on_update = on_update # 这个就是上面init定义的方法 class UpdateDictMixin(object):
# 这个类中定义了__setitem__和__delitem__ 会去执行self.on_update,修改self.modified的值
# 问题就出在这里,session["x"]=""才会去执行self.on_update,
# 但是如果session["x"]对应的是个数据结构,修改这个数据结构中的元素并不会去执行elf.on_update,
# session.modified就还是False,修不修改session就要看save_each and session.permanent了
# 如果他们之间有一个false就不会去修改,可以直接看到save_each存在与配置中
# ,而session.permanent在SessionMixin类中
on_update = None
def calls_update(name):
def oncall(self, *args, **kw):
rv = getattr(super(UpdateDictMixin, self), name)(*args, **kw)
if self.on_update is not None:
self.on_update(self)
return rv
oncall.__name__ = name
return oncall def setdefault(self, key, default=None):
modified = key not in self
rv = super(UpdateDictMixin, self).setdefault(key, default)
if modified and self.on_update is not None:
self.on_update(self)
return rv def pop(self, key, default=_missing):
modified = key in self
if default is _missing:
rv = super(UpdateDictMixin, self).pop(key)
else:
rv = super(UpdateDictMixin, self).pop(key, default)
if modified and self.on_update is not None:
self.on_update(self)
return rv __setitem__ = calls_update('__setitem__')
__delitem__ = calls_update('__delitem__')
clear = calls_update('clear')
popitem = calls_update('popitem')
update = calls_update('update')
del calls_update # session.permanent相关的
class SessionMixin(object):
# 取值时走这个方法
def _get_permanent(self):
return self.get('_permanent', False)
# 通过.设置值是走这个方法
def _set_permanent(self, value):
self['_permanent'] = bool(value)
# 这里不明白,为他设置值的时候会去调用on_update修改modified = True,如果设置了他
# SessionInterface中的should_set_cookie就会直接return True
# 而如果没设置就直接return session.permanent就好了,为什么还要and save_each
permanent = property(_get_permanent, _set_permanent)
del _get_permanent, _set_permanent new = False modified = True

  

将session存在其他地方

要将session存在其他地方,主要是和Flask中的session_interface属性对应的类实例有关系的.这些类要提供save_session和open_session方法

Flask的flask_session组件就提供了这些类

安装

pip install flask_session

用法

# 配置类,具体的配置是根据数据库类型设置的
class Config(object):
SECRET_KEY = "umsuldfsdflskjdf" # 加密用
PERMANENT_SESSION_LIFETIME = timedelta(minutes=20)
SESSION_TYPE = "redis"
SESSION_REDIS = Redis(host='192.168.0.94', port='6379') # 数据库连接,可以用连接池 from flask import Flask,session
from flask_session import Session
app = Flask(__name__)
app.config.from_object('Config')
Session(app)

Session干了什么

class Session(object):
def __init__(self, app=None):
self.app = app
if app is not None:
self.init_app(app) def init_app(self, app):
# 为flase实例赋了新的实例
app.session_interface = self._get_interface(app) def _get_interface(self, app):
# 根据配置来匹配不同的类
config = app.config.copy()
config.setdefault('SESSION_TYPE', 'null')
config.setdefault('SESSION_PERMANENT', True)
config.setdefault('SESSION_USE_SIGNER', False)
config.setdefault('SESSION_KEY_PREFIX', 'session:')
config.setdefault('SESSION_REDIS', None)
config.setdefault('SESSION_MEMCACHED', None)
config.setdefault('SESSION_FILE_DIR',
os.path.join(os.getcwd(), 'flask_session'))
config.setdefault('SESSION_FILE_THRESHOLD', 500)
config.setdefault('SESSION_FILE_MODE', 384)
config.setdefault('SESSION_MONGODB', None)
config.setdefault('SESSION_MONGODB_DB', 'flask_session')
config.setdefault('SESSION_MONGODB_COLLECT', 'sessions')
config.setdefault('SESSION_SQLALCHEMY', None)
config.setdefault('SESSION_SQLALCHEMY_TABLE', 'sessions') if config['SESSION_TYPE'] == 'redis':
session_interface = RedisSessionInterface(
config['SESSION_REDIS'], config['SESSION_KEY_PREFIX'],
config['SESSION_USE_SIGNER'], config['SESSION_PERMANENT'])
elif config['SESSION_TYPE'] == 'memcached':
session_interface = MemcachedSessionInterface(
config['SESSION_MEMCACHED'], config['SESSION_KEY_PREFIX'],
config['SESSION_USE_SIGNER'], config['SESSION_PERMANENT'])
elif config['SESSION_TYPE'] == 'filesystem':
session_interface = FileSystemSessionInterface(
config['SESSION_FILE_DIR'], config['SESSION_FILE_THRESHOLD'],
config['SESSION_FILE_MODE'], config['SESSION_KEY_PREFIX'],
config['SESSION_USE_SIGNER'], config['SESSION_PERMANENT'])
elif config['SESSION_TYPE'] == 'mongodb':
session_interface = MongoDBSessionInterface(
config['SESSION_MONGODB'], config['SESSION_MONGODB_DB'],
config['SESSION_MONGODB_COLLECT'],
config['SESSION_KEY_PREFIX'], config['SESSION_USE_SIGNER'],
config['SESSION_PERMANENT'])
elif config['SESSION_TYPE'] == 'sqlalchemy':
session_interface = SqlAlchemySessionInterface(
app, config['SESSION_SQLALCHEMY'],
config['SESSION_SQLALCHEMY_TABLE'],
config['SESSION_KEY_PREFIX'], config['SESSION_USE_SIGNER'],
config['SESSION_PERMANENT'])
else:
session_interface = NullSessionInterface() return session_interface

  

Flask请求流程超清大图的更多相关文章

  1. flask请求流程详解

    先看一个流程图: 1.当一个请求进入的时候,Flask框架首先会实例化一个Request Context,封装了请求信息,保存在Request中.生成请求上下文后,Flask框架会将请求上下文推入到_ ...

  2. flask请求流程

  3. flask源码剖析--请求流程

    想了解这篇里面的内容,请先去了解我另外一篇博客Flask上下文 在了解flask之前,我们需要了解两个小知识点 偏函数 import functools def func(a1,a2): print( ...

  4. python妹子图爬虫5千张高清大图突破防盗链福利5千张福利高清大图

    meizitu-spider python通用爬虫-绕过防盗链爬取妹子图 这是一只小巧方便,强大的爬虫,由python编写 所需的库有 requests BeautifulSoup os lxml 伪 ...

  5. 爬取5K分辨率超清唯美壁纸

    目录 爬取5K分辨率超清唯美壁纸 简介 编写思路 使用教程 演示图片 完整源代码 @ 爬取5K分辨率超清唯美壁纸 简介 壁纸的选择其实很大程度上能看出电脑主人的内心世界,有的人喜欢风景,有的人喜欢星空 ...

  6. flask请求钩子、HTTP响应、响应报文、重定向、手动返回错误码、修改MIME类型、jsonify()方法

    请求钩子: 当我们需要对请求进行预处理和后处理时,就可以用Flask提供的回调函数(钩子),他们可用来注册在请求处理的不同阶段执行的处理函数.这些请求钩子使用装饰器实现,通过程序实例app调用,以 b ...

  7. flask请求和应用上下文

    关于WSGI WSGI(全称Web Server Gateway Interface),是为 Python 语言定义的Web服务器和Web应用程序之间的一种简单而通用的接口,它封装了接受HTTP请求. ...

  8. DRF之REST规范介绍及View请求流程分析

    编程是数据结构和算法的结合,而在Web类型的App中,我们对于数据的操作请求是通过url来承载的,本文详细介绍了REST规范和CBV请求流程. 编程是数据结构和算法的结合,小程序如简单的计算器,我们输 ...

  9. 如何实现1080P延迟低于500ms的实时超清直播传输技术<转>

    转载地址:http://www.yunweipai.com/archives/9037.html 最近由于公司业务关系,需要一个在公网上能实时互动超清视频的架构和技术方案.众所周知,视频直播用 CDN ...

随机推荐

  1. protobuf 编译安装

    1.protobuf是google公司提出的数据存储格式,详细介绍可以参考:https://developers.google.com/protocol-buffers 2.下载最新的protobuf ...

  2. JAVA核心技术I---JAVA基础知识(类的继承)

    一:基本概念同C++一致 二:继承演示 .将共同点提取出来,即形成了父类/基类/超类 –Parent class/Base class/Super class .而其他类则自动成为子类/派生类 –Ch ...

  3. ibatis项目启动报错The string "--" is not permitted within comments【原】

    该错误主要就是因为xml中<!-- [注释]--> 注释与-->之间没有空格造成xml解析错误 sqlMapConfig.xml内容如下 <?xml version=" ...

  4. PHP7 网络编程(六)Socket和IO多路复用【待】

    https://blog.csdn.net/zhang197093/article/details/77366407

  5. Oracle12c开启scott账户

    在oracle目录app\orcl\product\12.1.0\dbhome_1\NETWORK\ADMIN\下tnsnames.ora文件最后加入以下内容 PDBORCL = (DESCRIPTI ...

  6. elementUi模态框使用baiduMap错误记录

    报错如下,可能是因为目标div还没生成 elementUi文档说明 在dom生成后再调用,正常 buildMap(){ let map = new BMap.Map("allmap" ...

  7. [ASNI C] [常用宏定义] [define技巧]

    1. 打印变量名及其值 #define Inquire(var, mode) fprintf(stdout, #var" = "#mode". \n", var ...

  8. talk命令帮助文档(ubuntu 18.04)

    TALK() BSD General Commands Manual TALK() NAME talk — talk to another user SYNOPSIS talk person [tty ...

  9. [译]在vuejs中使用任意js库

    原文 全局变量 最naive的办法是通过附加类库到window对象,使之成为全局变量: entry.js window._ = require('lodash'); MyComponent.vue e ...

  10. luogu 3538/bzoj 2795 Poi2008 哈希+质数结论

    题意:给定一个子串,询问一些子区间内的最短循环节(循环节是越短条件约束越多) 开始一看那就哈希处理然后暴力枚举循环节,然后按照循环节长度暴力向后比较,本地测试40,洛谷60 #include<b ...