flask 的g对象

在flask,g对象是专门用来存储用户数据的,它是global的缩写,g是全局变量,在整个request生命周期内生效。

1. g对象如何使用

这样解释,你可能无法透彻的理解,咱们来看看官方是如何解释的

The application context is created and destroyed as necessary. It never moves between threads and it will not be shared between requests. 
As such it is the perfect place to store database connection information and other things. The internal stack object is called flask.appctx_stack. 
Extensions are free to store additional information on the topmost level, assuming they pick a sufficiently unique name and 
should put their information there, instead of on the flask.g object which is reserved for user code

大意是说,像数据库配置这样重要的信息挂载在app对象上,一些用户相关的数据,就可以挂载在g对象上,这样就不需要在函数里一层层传递。

咱们举一个具体的例子,假设你想在处理请求时根据用户的vip等级来返回该用户的优惠券金额,下面的代码是对这一功能的的部分实现

from flask import Flask, request


app = Flask(__name__)


@app.route('/youhui')
def youhui():
    grade = request.args['grade']
    # 根据grade获得优惠券金额
    return '0'


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5500)

现在,还缺少一段根据grade获得优惠金额的代码,现在要求你编写一个函数来实现,那么你可以这样来写

def get_amount_by_grade(grade):
    if grade == 'a':
        return '100'
    else:
        return '80'

这样看起来是一个非常不错的解决方案,但事情往往不会这样简单,我在编写教程时尽可能将复杂场景简单化,这样你才看得懂。而真实的工作中,业务逻辑要比这复杂,相应的,代码逻辑,项目组织结构也比这复杂的多,真实的情况,可能不止grade一个参数需要传递,也不止传递一次。

许多技术的出现,不是造物主事先已经想好要它出现在哪里,而是实践中产生了需要,我们才将它造出来。现在,我需要一种技术,在不传递函数参数的情况下就能获得grade,这样,我的函数就没有那么多的参数了,且不管函数之间有怎样的调用关系,我都能在需要的地方获得我想要的用户数据。此时,你需要的就是g对象。

from flask import Flask, request, g


app = Flask(__name__)


@app.route('/youhui')
def youhui():
    grade = request.args['grade']
    g.grade = grade
    return get_amount_by_grade()


def get_amount_by_grade():
    grade = g.grade
    if grade == 'a':
        return '100'
    else:
        return '80'

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5500)

g对象的出现,让你在任何位置都能获得用户数据,避免了在函数参数里传递这些数据。

2. g对象的生命周期

你需要正确理解g对象的生命周期,在文章开头,我已经讲明,g对象在整个request请求处理期间生效,这表明,g对象是与request是一一对应的。一次request请求,就有一个g对象,在这次请求之前,之后,以及同时间的请求里,他们互不干扰。

你在g对象里存储的数据,只能在这一次请求里使用,请求处理结束后,这个g对象就销毁了,存储的数据也就不见了。

g对象的生命周期虽然只是一次请求的生命周期,但它是一个应用 上下文对象

request = LocalProxy(partial(_lookup_req_object, "request"))
session = LocalProxy(partial(_lookup_req_object, "session"))
g = LocalProxy(partial(_lookup_app_object, "g"))

request和session是请求上下文对象,g对象的生命周期虽然和request相同,但的的确确是个应用上下文对象。这样设计是考虑flask也可以在非web场合下使用,如果g对象是请求上下文,那么在使用g对象时还需要手动构建一个请求,明显是不合理的。

扫描关注, 与我技术互动

QQ交流群: 211426309

加入知识星球, 每天收获更多精彩内容

分享日常研究的python技术和遇到的问题及解决方案