flask基础之AppContext应用上下文和RequestContext请求上下文(六)

前言

应用上下文和请求上下文存在的目的,官方文档讲的很清楚,可参考:

http://www.pythondoc.com/flask/appcontext.html

应用上下文对象在没有请求的时候是可以单独存在的,但是请求上下文对象只有在收到请求后才会被创建。请求处理和应用上下文和请求上下文的关系是:

接收请求--》创建请求上下文--》请求上下文入栈--》创建该请求的应用上下文--》应用上下文入栈--》处理逻辑--》请求上下文出栈--》应用上下文出栈

系列文章

请求上下文RequestContext

请求上下文管理着请求对象Request,会话对象Session,当前请求的app应用,为了保证在一个请求的周期内的任何时候任何地点访问到Request和Session,又不能发生循环导入的问题,flask使用代理对象request和session来代理当前请求的Request和Session。

request = LocalProxy(partial(_lookup_req_object, ‘request‘))
session = LocalProxy(partial(_lookup_req_object, ‘session‘))

RequestContext分析

flask框架处理请求的第一步就是收到请求后创建请求上下文RequestContext.

class RequestContext(object):
    def __init__(self, app, environ, request=None):
        self.app = app
        if request is None:
            request = app.request_class(environ) # 使用app的Request对象创建一个实例
        self.request = request # 请求上下文的request
        self.url_adapter = app.create_url_adapter(self.request)
        self.flashes = None
        self.session = None # 请求上下文的session
        self._implicit_app_ctx_stack = [] # 请求上下文的应用上下文临时存放点
        self.preserved = False
        self._preserved_exc = None
        self._after_request_functions = []
        self.match_request() # 提取请求的路由创建request对象的Rule对象

request

request作为一个代理对象,其指向的是当前的请求的请求上下文RequestContext对象的request属性,即在请求上下文初始化的时候创建的请求对象,它是程序处理逻辑频繁需要的对象,存储着几乎所有的请求数据信息,本质上是Request对象。生命周期为一次请求期间,当请求处理完成后被销毁;

class Request(RequestBase):
    url_rule = None # 记录本次请求的Rule对象
    view_args = None # 本次请求的参数,指的是用路由转化器得到的参数
    routing_exception = None # 如果路由匹配失败,记录错误对象

# 重要的属性
request.max_content_length # 获取该请求允许的数据包最大字节数
request.endpoint # 获取该请求的rule的标识符
request.url_charset # 获取url的编码
request.blueprint # 请求属于的蓝图

# 和路由相关的属性
print(request.url_root)
print(request.url)
print(request.url_rule)
print(request.host_url)
print(request.base_url)
print(request.path) # 路由路径,如/time
print(request.full_path) # 全路径,包括参数
print(request.script_root)
print(request.host) # 服务器的ip
print(request.access_route) # 所有转发的ip地址列表
print(request.remote_addr) # 客户端远程地址
# 结果
http://192.168.1.112:8000/
http://192.168.1.112:8000/time/time?a=1
/time/time
http://192.168.1.112:8000/
http://192.168.1.112:8000/time/time

# 获取请求数据
print(request.is_json) # 判断请求数据是否是json格式
print(request.get_json()) # 获取json数据
print(request.args) # 获取url中的参数作为字典返回,没有返回空对象
print(request.form) # 获取表单数据
print(request.values) # 同时获取表单数据和url参数
print(request.data) # 没有被其他格式解析成功的数据
print(request.files) # 获取上传的文件
print(request.cookies) # 获取cookie
print(request.headers) # 获取头部信息

session

session代理的是请求上下文RequestContext对象的session属性,其是在请求上下文被推送到栈的时候创建的session对象,类似一个字典的容器。每次请求创建的session实例都是新的,随着请求上下文被销毁而销毁。

关于flask的session实现机制和运用参考: flask基础之session机制详解

应用上下文AppContext

应用上下文对象AppContext会在必要时被创建和销毁,它不会在线程间移动,并且也不会在不同的请求之间共享;因此它可以作为在一次请求中临时存放数据的地方,其主要管理本次请求的当前应用app对象和临时全局g对象。

current_app = LocalProxy(_find_app)
g = LocalProxy(partial(_lookup_app_object, ‘g‘))

AppContext分析

flask的应用上下文可以主动创建,在不需要发生http请求的情况下;当请求上下文被推送到栈后,该请求的应用上下文会跟着创建加入栈中。

class AppContext(object):
    def __init__(self, app):
        self.app = app
        self.url_adapter = app.create_url_adapter(None)
        self.g = app.app_ctx_globals_class() # app的全局变量

current_app

current_app代理的就是当前的应用,我们可以在业务处理的任何时候通过current_app获取应用app的任何属性,之所以要这样做是为了避免app对象被到处显性传递造成循环导入的错误。current_app存在于应用上下文活跃期间,会在请求处理完成后,随着应用上下文销毁而销毁

from flask import current_app

app = Flask(__name__)
with app.app_context():
    current_app.url_map

current_app必须在应用上下文被创建并且被推送后才能使用。

g

g一般的用法是在请求期间管理资源,其指向的是当前应用的app_ctx_globals_class属性,是一个_AppCtxGlobals对象;g对象是随着应用上下文生存或死亡。

class _AppCtxGlobals(object):
    # 从g中获取数据
    def get(self, name, default=None):
        pass
    # 获取数据并且弹出
    def pop(self, name, default=_sentinel):
        pass
    # 在g中添加键值对,如果存在则忽略
    def setdefault(self, name, default=None):
        pass

我们可以将g对象看做dict的数据结构,它支持g.ab方式获取值和赋值。

with app.app_context():
    g.ab = ‘name‘ # 将{‘ab’:‘name‘}键值对添加到g中
    x = g.ab # 获取ab的值,如果没有会报错,所以推荐使用g.get(‘ab‘)方法

总结

  • 请求上下文面向开发者使用的对象主要是request和session;
  • 应用上下文面向开发者使用的对象主要是current_app和g;
  • 一次请求期间,请求上下文创建后会创建对应的本次请求的应用上下文;
  • 请求上下文一般不可以单独存在,因为创建请求上下文需要请求数据作为参数;但是应用上下文可以单独存在并且可以手动推送;

参考

原文地址:https://www.cnblogs.com/cwp-bg/p/9933854.html

时间: 2024-10-01 06:35:37

flask基础之AppContext应用上下文和RequestContext请求上下文(六)的相关文章

flask基础之请求处理核心机制(五)

前言 总结一下flask框架的请求处理流程. 系列文章 flask基础之安装和使用入门(一) flask基础之jijia2模板使用基础(二) flask基础之jijia2模板语言进阶(三) flask基础之app初始化(四) WSGI协议 一般来说http服务器和框架需要进行解耦,http专门负责接受HTTP请求.解析HTTP请求.发送HTTP,响应请求等:而web框架负责处理请求的逻辑,和数据库的交互等等,那么它们之间需要约定一套接口使得http服务器能够调用web框架的处理逻辑,这个协议就是

flask基础之app初始化(四)

前言 flask的核心对象是Flask,它定义了flask框架对于http请求的整个处理逻辑.随着服务器被启动,app被创建并初始化,那么具体的过程是这样的呢? 系列文章 flask基础之安装和使用入门(一) flask基础之jijia2模板使用基础(二) flask基础之jijia2模板语言进阶(三) 一个最基本web应用的flask代码 from flask import Flask import os # 创建app对象 app = Flask(__name__,template_fold

视频版|Flask 基础与 Web 开发实战

公开课主题:Flask 基础与 Web 开发实战 主要内容: 一.Web 开发基础 二.在 Flask 中的 "Hello World" 三.Flask 的模版 四.Flask 的消息提示与异常处理 主讲师:Nick 担任某上市公司运维开发岗,在公司主导运维自动化的开发与运维前沿技术的落地,近两年也一直专注于运维开发转型和实践,从运维到运维开发一路走来,很愿意与大家分享在转型过程中的五谷杂粮. 视频

Flask基础(12)-->Flask扩展Flask-Script

Flask基础(12)-->Flask扩展Flask-Script # 前提是安装了Flask-Script # 联网运行 pip install flask-script from flask import Flask from flask_script import Manager # 导入Manger app = Flask(__name__) # 创建Flask对象 class Config(object): DEBUG = True app.config.from_object(Con

flask基础四

内容回顾: 1.Flask-Session        from flask import session        from flask_session import Session                app.config["SESSTION_TPYE"] = "redis"        app.config["SESSTION_REDIS"] = Redis("ip",port,db=1)      

flask基础之Response响应对象(九)

前言 Response对象负责对客户端的响应,每一个请求都会有一个Response对象,那么它在一个请求的声明周期内是怎么发挥作用的呢? Response对象 响应发生的位置 先回顾一下http请求的flask处理流程: 接收请求-->创建请求上下文-->请求上下文入栈-->创建该请求的应用上下文-->应用上下文入栈-->调用视图函数处理逻辑-->请求上下文出栈-->应用上下文出栈 Response对象在调用视图函数处理逻辑后就被创建,但是对客户端的响应在应用上下

flask 请求上下文源码(转)

本篇阅读目录 一.flask请求上下文源码解读 二.http聊天室(单聊/群聊)- 基于gevent-websocket 回到顶部 转:https://www.cnblogs.com/li-li/p/10252058.html#main 一.flask请求上下文源码解读 通过上篇源码分析,我们知道了有请求发来的时候就执行了app(Flask的实例化对象)的__call__方法,而__call__方法返回了app的wsgi_app(environ, start_response)方法的执行结果,而

java基础知识回顾之java Thread类学习(六)--java多线程同步函数用的锁

1.验证同步函数使用的锁----普通方法使用的锁 思路:创建两个线程,同时操作同一个资源,还是用卖票的例子来验证.创建好两个线程t1,t2,t1线程走同步代码块操作tickets,t2,线程走同步函数封装的代码操作tickets,同步代码块中的锁我们可以指定.假设我们事先不知道同步函数用的是什么锁:如果在同步代码块中指定的某个锁(测试)和同步函数用的锁相同,就不会出现线程安全问题,如果锁不相同,就会发生线程安全问题. 看下面的代码:t1线程用的同步锁是obj,t2线程在操作同步函数的资源,假设不

应用上下文和请求上下文

from flask import Flask,request,session,url_for,current_app from werkzeug.local import Local,LocalStack #线程隔离技术 #只要绑定在Local对象上的属性 #在每个线程中都是隔离 app = Flask(__name__) # print(current_app.name)#RuntimeError: Working outside of application context. #怎么解决上