# 4.2 AppContext、RequestContext、Flask与Request之间的关系

## 1.定位AppContext、RequestContext

Flask有两个上下文，应用上下文-AppContext和请求上下文-RequestContext。他们本质都是对象，是一种封装。应用上下文是对Flask的封装，请求上下文是对Request的封装

下面我们来通过源码，了解一下这两个上下文。 Flask源码的全貌，是在External Libraries/site-pacages/flask下![image.png](https://upload-images.jianshu.io/upload_images/7220971-a5d3da76a5ee10e1.png?imageMogr2/auto-orient/strip|imageView2/2/w/1240) Flask是一个非常好的微框架，里面的源码并不多，大部分都是注释，这给我们可以很方便的阅读源码

我们要看的两个上下文在ctx.py（context的缩写）中，其中的AppContext就是应用上下文，RequestContext就是请求上下文 ![image.png](https://upload-images.jianshu.io/upload_images/7220971-75e04ffc4f79a77d.png?imageMogr2/auto-orient/strip|imageView2/2/w/1240)

阅读AppContext和RequestContext的构造函数，发现他们都将核心对象app作为了他们的一个属性

```
    def __init__(self, app):
        self.app = app
        self.url_adapter = app.create_url_adapter(None)
        self.g = app.app_ctx_globals_class()

        # Like request context, app contexts can be pushed multiple times
        # but there a basic "refcount" is enough to track them.
        self._refcnt = 0
```

并且他们都有相同的四个方法

```
def push(self):
    ...
def pop(self, exc=_sentinel):
    ...
def __enter__(self):
    ...
def __exit__(self, exc_type, exc_value, tb):
    ...
```

## 2.为什么需要上下文

为什么需要上下文，我们之间操作Flask的核心对象app不可以吗？

这是一个设计思想。有时候呢，我们不光需要这个核心对象app，还需要他外部的一些东西，这个时候，我们可以他们统一结合封装到一起，组装成一个新的上下文对象，并且在这个对象之上，可以提供一些新的方法，如我们上面所提到的push、pop等

## 3.对AppContext、RequestContext、Flask与Request的意义做出一个解释

* Flask：核心对象，核心对象里承载了各种各样的功能，比如保存配置信息，再比如注册路由试图函数等
* AppContext：对Flask的封装，并且增加了一些额外的参数
* Request：保存了请求信息，比如url的参数，url的全路径等信息
* RequestContext：对Request的封装

我们在实际编码过程中，可能是需要Flask或者Request的信息的，但是这并不代表我们应该直接导入这两个对象获取相关信息，正确的做法是从AppContext，RequestContext中间接的获得我们需要的信息

即使这样，我们也没有必要导入Context去使用上下文，这就回到了current\_app和request这些LocalProxy，他们提供了间接操作上下文对象的能力，使用了代理模式
