Como um adendo às informações neste tópico: Também fiquei um pouco confuso com o comportamento flask.g
, mas alguns testes rápidos me ajudaram a esclarecê-lo. Aqui está o que eu tentei:
from flask import Flask, g
app = Flask(__name__)
with app.app_context():
print('in app context, before first request context')
print('setting g.foo to abc')
g.foo = 'abc'
print('g.foo should be abc, is: {0}'.format(g.foo))
with app.test_request_context():
print('in first request context')
print('g.foo should be abc, is: {0}'.format(g.foo))
print('setting g.foo to xyz')
g.foo = 'xyz'
print('g.foo should be xyz, is: {0}'.format(g.foo))
print('in app context, after first request context')
print('g.foo should be abc, is: {0}'.format(g.foo))
with app.test_request_context():
print('in second request context')
print('g.foo should be abc, is: {0}'.format(g.foo))
print('setting g.foo to pqr')
g.foo = 'pqr'
print('g.foo should be pqr, is: {0}'.format(g.foo))
print('in app context, after second request context')
print('g.foo should be abc, is: {0}'.format(g.foo))
E aqui está o resultado que ele fornece:
in app context, before first request context
setting g.foo to abc
g.foo should be abc, is: abc
in first request context
g.foo should be abc, is: abc
setting g.foo to xyz
g.foo should be xyz, is: xyz
in app context, after first request context
g.foo should be abc, is: xyz
in second request context
g.foo should be abc, is: xyz
setting g.foo to pqr
g.foo should be pqr, is: pqr
in app context, after second request context
g.foo should be abc, is: pqr
Como o Y4Kman disse acima, "Toda solicitação impulsiona um novo contexto de aplicativo". E, como dizem os documentos do Flask , o contexto do aplicativo "não será compartilhado entre solicitações". Agora, o que não foi declarado explicitamente (embora eu ache que esteja implícito nessas declarações) e o que meus testes mostram claramente é que você nunca deve criar explicitamente vários contextos de solicitação aninhados dentro de um contexto de aplicativo, porque flask.g
(e co) não ' não possui mágica em que funcione nos dois "níveis" diferentes de contexto, com estados diferentes existindo independentemente nos níveis de aplicação e solicitação.
A realidade é que "contexto de aplicativo" é potencialmente um nome enganoso, porque app.app_context()
é um contexto por solicitação , exatamente o mesmo que "contexto de solicitação" . Pense nisso como uma "lista de contexto de solicitação", necessária apenas no caso em que você precisa de algumas das variáveis que normalmente requerem um contexto de solicitação, mas não precisa de acesso a nenhum objeto de solicitação (por exemplo, ao executar operações de banco de dados em lote em um shell script). Se você tentar estender o contexto do aplicativo para abranger mais de um contexto de solicitação, estará solicitando problemas. Portanto, em vez do meu teste acima, você deve escrever um código como este nos contextos do Flask:
from flask import Flask, g
app = Flask(__name__)
with app.app_context():
print('in app context, before first request context')
print('setting g.foo to abc')
g.foo = 'abc'
print('g.foo should be abc, is: {0}'.format(g.foo))
with app.test_request_context():
print('in first request context')
print('g.foo should be None, is: {0}'.format(g.get('foo')))
print('setting g.foo to xyz')
g.foo = 'xyz'
print('g.foo should be xyz, is: {0}'.format(g.foo))
with app.test_request_context():
print('in second request context')
print('g.foo should be None, is: {0}'.format(g.get('foo')))
print('setting g.foo to pqr')
g.foo = 'pqr'
print('g.foo should be pqr, is: {0}'.format(g.foo))
O que dará os resultados esperados:
in app context, before first request context
setting g.foo to abc
g.foo should be abc, is: abc
in first request context
g.foo should be None, is: None
setting g.foo to xyz
g.foo should be xyz, is: xyz
in second request context
g.foo should be None, is: None
setting g.foo to pqr
g.foo should be pqr, is: pqr
g
na 0.10, caso contrário, parece que muito código pode começar a desenvolver alguns erros desonestos.