上下文本质

1
2
3
4
5
6
7
8
- 当请求过来后,将请求相关数据添加到 Local()类中
    {
        线程或协程唯一标识:{"stack":[request]},
        线程或协程唯一标识:{"stack":[]},
        线程或协程唯一标识:{"stack":[]}
    }
- 以后使用时 去读取
- 请求完成之后,将request从列表中移除

Flask源码

1
2
3
4
5
6
7
8
9
10
11
from flask import Flask,session,request
 
app = Flask(__name__)
 
@app.route("/login",methods=["GET","POST"])
def login():
    return "index"
 
if __name__ == '__main__':
    #app.__call__()
    app.run()

1. 执行app.__call__方法

def __call__(self, environ, start_response):
return self.wsgi_app(environ, start_response)

2. 执行wsgi_app方法

def wsgi_app(self, environ, start_response):

    ctx = self.request_context(environ)
ctx.push() response = self.full_dispatch_request()

2.1 生成RequestContext()对象 封装请求相关的数据(request,session)

1
ctx = self.request_context(environ)
def request_context(self, environ):
return RequestContext(self, environ) class RequestContext(object):
def __init__(self, app, environ, request=None):
self.app = app
if request is None:
request = app.request_class(environ)
self.request = request

2.2 将用户请求数据封装到Local()类中

1
ctx.push()
def push(self):

    from .globals import _request_ctx_stack

    #将请求数据封装到Local()类
_request_ctx_stack.push(self) #处理session
self.session = self.app.open_session(self.request)
if self.session is None:
self.session = self.app.make_null_session()

2.2.1 导入 _request_ctx_stack对象  内部会自动生成  { 线程或协程唯一标识:{"stack":[]} } 格式

1
from .globals import _request_ctx_stack
class Local(object):

    def __init__(self):
object.__setattr__(self, '__storage__', {})
object.__setattr__(self, '__ident_func__', get_ident) def __setattr__(self, name, value):
ident = self.__ident_func__()
storage = self.__storage__
try:
storage[ident][name] = value
except KeyError:
storage[ident] = {name: value} class LocalStack(object): def __init__(self):
self._local = Local() def push(self, obj):
rv = getattr(self._local, 'stack', None)
if rv is None:
self._local.stack = rv = []
rv.append(obj)
return rv _request_ctx_stack = LocalStack()

2.2.2 执行_request_ctx_stack对象push方法  触发Local类的__setattr__方法 生成  { 线程或协程唯一标识:{"stack":[ RequestContext对象 ]} }

1
_request_ctx_stack.push(self)
class Local(object):

    def __setattr__(self, name, value):
ident = self.__ident_func__()
storage = self.__storage__
try:
storage[ident][name] = value
except KeyError:
storage[ident] = {name: value} class LocalStack(object): def push(self, obj):
"""Pushes a new item to the stack"""
rv = getattr(self._local, 'stack', None)
if rv is None:
self._local.stack = rv = [] rv.append(obj)
return rv _request_ctx_stack = LocalStack()

2.2.3 self.session重新赋值

1
2
3
4
RequestContext类的 self.session由none重新赋值为SecureCookieSessionInterface类open_session方法的结果(SecureCookieSession对象)
    - SecureCookieSession对象 就是一个字典
 
self.session = self.app.open_session(self.request)
def open_session(self, request):
return self.session_interface.open_session(self, request) # 之后这里可以自定义自己类 可以继承SecureCookieSessionInterface类
session_interface = SecureCookieSessionInterface() class SecureCookieSessionInterface(SessionInterface): def open_session(self, app, request):
s = self.get_signing_serializer(app)
if s is None:
return None # 去cookie中获取session作为key 对应的值(包含了此用户的session数据)
val = request.cookies.get(app.session_cookie_name)
if not val:
return self.session_class()
max_age = total_seconds(app.permanent_session_lifetime)
try:
data = s.loads(val, max_age=max_age)
return self.session_class(data)
except BadSignature:
return self.session_class()

3. 之后调用request

#此时你如果调用request 会执行如下代码
request = LocalProxy(partial(_lookup_req_object, 'request'))
_lookup_req_object 获取RequestContext()中用户的请求数据

4. 执行视图函数

1
response = self.full_dispatch_request()

4.1 触发只执行一次的装饰器函数 @before_first_request 

self.try_trigger_before_first_request_functions()

4.2 # 触发Flask的信号  需要pip3 install blinker

1
request_started.send(self)

4.3 执行特殊装饰器  @before_request

有返回值 返回用户
没有返回值 触发并执行视图函数
rv = self.preprocess_request()
if rv is None:
rv = self.dispatch_request()

4.4 执行请求之后的装饰器  @after_request  且处理session

return self.finalize_request(rv)

    def finalize_request(self, rv, from_error_handler=False):

        response = self.process_response(response)

            def process_response(self, response):

                # 处理session
if not self.session_interface.is_null_session(ctx.session):
self.save_session(ctx.session, response)

 

 

  

  

  

  

  

f'lask源码的更多相关文章

  1. RDD.scala(源码)

    ---- map. --- flatMap.fliter.distinct.repartition.coalesce.sample.randomSplit.randomSampleWithRange. ...

  2. LinkedList 基本示例及源码解析

    目录 一.JavaDoc 简介 二.LinkedList 继承接口和实现类介绍 三.LinkedList 基本方法介绍 四.LinkedList 基本方法使用 五.LinkedList 内部结构以及基 ...

  3. 源码分析:Exchanger之数据交换器

    简介 Exchanger是Java5 开始引入的一个类,它允许两个线程之间交换持有的数据.当Exchanger在一个线程中调用exchange方法之后,会阻塞等待另一个线程调用同样的exchange方 ...

  4. 2017年中国大学生程序设计竞赛-中南地区赛暨第八届湘潭市大学生计算机程序设计大赛题解&源码(A.高斯消元,D,模拟,E,前缀和,F,LCS,H,Prim算法,I,胡搞,J,树状数组)

    A------------------------------------------------------------------------------------ 题目链接:http://20 ...

  5. 【原】FMDB源码阅读(二)

    [原]FMDB源码阅读(二) 本文转载请注明出处 -- polobymulberry-博客园 1. 前言 上一篇只是简单地过了一下FMDB一个简单例子的基本流程,并没有涉及到FMDB的所有方方面面,比 ...

  6. 【原】FMDB源码阅读(一)

    [原]FMDB源码阅读(一) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 说实话,之前的SDWebImage和AFNetworking这两个组件我还是使用过的,但是对于 ...

  7. 一篇文章看懂TPCx-BB(大数据基准测试工具)源码

    TPCx-BB是大数据基准测试工具,它通过模拟零售商的30个应用场景,执行30个查询来衡量基于Hadoop的大数据系统的包括硬件和软件的性能.其中一些场景还用到了机器学习算法(聚类.线性回归等).为了 ...

  8. OpenCV人脸识别LBPH算法源码分析

    1 背景及理论基础 人脸识别是指将一个需要识别的人脸和人脸库中的某个人脸对应起来(类似于指纹识别),目的是完成识别功能,该术语需要和人脸检测进行区分,人脸检测是在一张图片中把人脸定位出来,完成的是搜寻 ...

  9. zookeeper源码分析之五服务端(集群leader)处理请求流程

    leader的实现类为LeaderZooKeeperServer,它间接继承自标准ZookeeperServer.它规定了请求到达leader时需要经历的路径: PrepRequestProcesso ...

随机推荐

  1. HDU.1285 确定比赛名次 (拓扑排序 TopSort)

    HDU.1285 确定比赛名次 (拓扑排序 TopSort) 题意分析 裸的拓扑排序 详解请移步 算法学习 拓扑排序(TopSort) 只不过这道的额外要求是,输出字典序最小的那组解.那么解决方案就是 ...

  2. bzoj2761: [JLOI2011]不重复数字(hash)

    题目大意:给出N个数,要求把其中重复的去掉,只保留第一次出现的数.例如,给出的数为1 2 18 3 3 19 2 3 6 5 4,其中2和3有重复,去除后的结果为1 2 18 3 19 6 5 4. ...

  3. 【链表】【UVA11988】Broken Keyboard

    传送门 明明是道黄题我竟然来写博客……我真的是什么数据结构也不会写了 Description 你在输入文章的时候,键盘上的Home键和End键出了问题,会不定时的按下.你却不知道此问题,而是专心致志地 ...

  4. 负载均衡配置(基于Nginx)

    以下是基于nginx进行负载均衡配置的流程: 服务器配置如下: 1.  安装nginx的服务器:192.168.1.1 2.  nginx配置负载均衡位置及端口:192.168.1.1 80端口 3. ...

  5. Java中equals和==的区别?为什么重写equals方法后,一定要重写hashCode方法?

    首先明确一点,equals是方法,==是操作符. 1. 如果比较的是基本数据类型: 只讨论==,因为equals是不存在的,因为java中基本数据类型不能调用method的. 2. 如果比较的是引用类 ...

  6. Java注释@interface的用法【转】 --好文章 很好理解

    java用  @interface Annotation{ } 定义一个注解 @Annotation,一个注解是一个类. @Override,@Deprecated,@SuppressWarnings ...

  7. Stirling数笔记

    Updating.... 这几个玩意儿要记的东西太多太乱所以写blog整理一下 虽然蒯的成分会比较多全部 我居然开始记得写blog了?? 第一类 这里讨论的是无符号类型的. OEIS编号A130534 ...

  8. Chrome切换分辨率

    不知道大家是否有遇到在Web开发的时候,老大会让你模拟不同分辨率情况,这时候,可能就有些小小的麻烦,我们可能要不断调整分辨率.是件很崩溃的事情.现在推荐一款Chrome插件.即可实现这个简单的功能. ...

  9. python+selenium+js 处理滚动条

    selenium并不是万能的,有时候页面上操作无法实现的,这时候就需要借助JS来完成了. 常见场景: 当页面上的元素超过一屏后,想操作屏幕下方的元素,是不能直接定位到,会报元素不可见的. 这时候需要借 ...

  10. UOJ#204 【APIO2016】Boat

    Time Limit: 70 Sec  Memory Limit: 256 MBSubmit: 559  Solved: 248 Description 在首尔城中,汉江横贯东西.在汉江的北岸,从西向 ...