补充一下

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. ARM寄存器介绍

    ARM处理器共有37个寄存器.其中包括:31个通用寄存器,包括程序计数器(PC)在内.这些寄存器都是32位寄存器.以及6个32位状态寄存器.但目前只使用了其中12位.ARM处理器共有7种不同的处理器模 ...

  2. 【leetcode70】【动态规划】 爬楼梯

    (1 pass 一维动态规划) 爬楼梯(easy) 假设你正在爬楼梯.需要 n 阶你才能到达楼顶. 每次你可以爬 1 或 2 个台阶.你有多少种不同的方法可以爬到楼顶呢? 注意:给定 n 是一个正整数 ...

  3. python 有趣的库练习

    这里会将看到别人玩过有趣的实践并记录下来,会是一个长期更新的过程... 以下大部分均非原创变化自网络,只是觉得有趣便记录下来了,如有侵权,请告知删除... 自动化脚本... 20个必不可少的Pytho ...

  4. sqlalchemy外键和relationship查询

    前面的文章中讲解了外键的基础知识和操作,上一篇文章讲解了sqlalchemy的基本操作.前面两篇文章都是作为铺垫,为下面的文章打好基础.记得初一时第一次期中考试时考的不好,老爸安慰我说:“学习是一个循 ...

  5. 使用wget命令下载JDK失败(文件特别小)

    问题RT: 我们在网页上下载的时候要点一下 “Accept License Agreement ” ,使用wget下载的时候也需要提交这个 accept,方法如下: wget --no-check-c ...

  6. ASP.NET Web API 2 消息处理管道

    Ø  前言 ASP.NET 的应用程序都会有自己的消息处理管道和生命周期,比如:ASP.NET Web 应用程序(Web Form).ASP.NET MVC,还有本文将讨论的 ASP.NET Web ...

  7. inetd.conf文件中的字段

  8. url 组成部分

    NSURL其实就是我们在浏览器上看到的网站地址,这不就是一个字符串么,为什么还要在写一个NSURL呢,主要是因为网站地址的字符串都比较复杂,包括很多请求参数,这样在请求过程中需要解析出来每个部门,所以 ...

  9. 【LeetCode】335. Self Crossing(python)

    Problem:You are given an array x of n positive numbers. You start at point (0,0) and moves x[0] metr ...

  10. Food Log with Speech Recognition and NLP

    1. 分词 word segmentation 国内有jieba 分词 2. Named Entity Recognition 训练自己的Model How can I train my own NE ...