上下文本质

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. 【状压DP】【UVA11795】 Mega Man's Mission

    传送门 Description 你要杀n个怪,每杀掉一个怪那个怪会掉落一种武器,这种武器可以杀死特定的怪.游戏初始你有一把武器,能杀死一些怪物.每次只能杀一只,求有多少种杀怪方法. Input 多组数 ...

  2. 用JQuery实现自定义选择桌面

    有些时候,我们可以为用户提供很贴心的功能,比如判断用户是什么时候来访问的,然后给出一句问候,晚上好,下午好之类的.并且更换网页的背景颜色,比如晚上的时候就可以用满天星星的背景,白天就用阳光灿烂,或者特 ...

  3. ACE线程管理机制-并发控制(3)

    转载于:http://www.cnblogs.com/TianFang/archive/2006/12/04/581854.html ACE Condition类属 ACE Condition类属(条 ...

  4. Sightseeing(dijlstar) 计算最短路和次短路的条数

    Sightseeing Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 10004   Accepted: 3523 Desc ...

  5. DOM动态操纵控件案例

    点击登陆显示登陆框 <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head ...

  6. 手脱ACProtect V1.4X(有Stolen Code)之补区段

    首先需要说的是,这个壳是ximo大神视频教程里的 0041F000 > pushad ; //程序入口点 0041F001 E8 call NgaMy.0041F007 0041F006 E8 ...

  7. 关于移动DSP

    提  纲 1.移动DSP与传统营销有什么不同? 2.为什么移动DSP是大势所趋? 3.哪些因素决定移动DSP的精准与否? 4.如何辨别移动DSP的真伪优劣? 5.不同行业的广告主如何用好移动DSP? ...

  8. 【通用邮件发送】C# QQ 网易邮箱

    using BooksStore.Domain.Models; using System; using System.Collections.Generic; using System.Linq; u ...

  9. spring和Quartz的集群(二)

    一:前沿 写完了这两篇才突然想起来,忘记了最关键的东西,那就是在配置文件这里的配置,还有数据库的配置.这是郁闷啊!继续吧! 二:内容配置 我们在集成的时候需要自己配置一个quartz.properti ...

  10. Lucene4.6至 Lucene6.6的每个迭代对API的改动

    由于项目需求,需要将Lucene4.6升级到Lucene6.6,因此我对这之间的所有重要的API改动做了搜集:特别重要的改变加粗显示. Lucene4.7改动: LUCENE-5405: Make S ...