Come addendum alle informazioni in questo thread: sono stato un po 'confuso anche dal comportamento di flask.g
, ma alcuni test rapidi mi hanno aiutato a chiarirle. Ecco cosa ho provato:
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))
Ed ecco l'output che dà:
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
Come detto sopra da Y4Kman, "Ogni richiesta introduce un nuovo contesto applicativo". E come dicono i documenti di Flask , il contesto dell'applicazione "non sarà condiviso tra le richieste". Ora, ciò che non è stato esplicitamente dichiarato (anche se immagino sia implicito da queste affermazioni), e ciò che i miei test mostrano chiaramente, è che non dovresti mai creare esplicitamente contesti di richieste multiple nidificati all'interno di un contesto di applicazione, perché flask.g
(e co) non lo fanno Non ha alcuna magia per cui funzioni nei due diversi "livelli" di contesto, con stati diversi esistenti indipendentemente ai livelli di applicazione e richiesta.
La realtà è che "contesto applicativo" è potenzialmente un nome abbastanza fuorviante, perché app.app_context()
è un contesto per richiesta , esattamente lo stesso del "contesto richiesta" . Consideralo come un "lite di contesto di richiesta", richiesto solo nel caso in cui hai bisogno di alcune delle variabili che normalmente richiedono un contesto di richiesta, ma non hai bisogno di accedere a nessun oggetto di richiesta (ad es. Quando esegui operazioni DB batch in un shell script). Se si tenta di estendere il contesto dell'applicazione per includere più di un contesto di richiesta, si stanno verificando problemi. Quindi, piuttosto che il mio test sopra, dovresti invece scrivere codice come questo con i contesti di 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))
Che darà i risultati attesi:
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
in 0.10, altrimenti sembra che un sacco di codice potrebbe iniziare a sviluppare alcuni bug subdoli.