En complément des informations de ce fil : j'ai été un peu confus par le comportement de flask.g
également, mais quelques tests rapides m'ont aidé à le clarifier. Voici ce que j'ai essayé :
from flask import Flask, g
app = Flask(__name__)
with app.app_context():
print('dans le contexte de l'application, avant le premier contexte de requête')
print('définition de g.foo à abc')
g.foo = 'abc'
print('g.foo devrait être abc, est : {0}'.format(g.foo))
with app.test_request_context():
print('dans le premier contexte de requête')
print('g.foo devrait être abc, est : {0}'.format(g.foo))
print('définition de g.foo à xyz')
g.foo = 'xyz'
print('g.foo devrait être xyz, est : {0}'.format(g.foo))
print('dans le contexte de l'application, après le premier contexte de requête')
print('g.foo devrait être abc, est : {0}'.format(g.foo))
with app.test_request_context():
print('dans le second contexte de requête')
print('g.foo devrait être abc, est : {0}'.format(g.foo))
print('définition de g.foo à pqr')
g.foo = 'pqr'
print('g.foo devrait être pqr, est : {0}'.format(g.foo))
print('dans le contexte de l'application, après le second contexte de requête')
print('g.foo devrait être abc, est : {0}'.format(g.foo))
Et voici le résultat obtenu :
dans le contexte de l'application, avant le premier contexte de requête
définition de g.foo à abc
g.foo devrait être abc, est : abc
dans le premier contexte de requête
g.foo devrait être abc, est : abc
définition de g.foo à xyz
g.foo devrait être xyz, est : xyz
dans le contexte de l'application, après le premier contexte de requête
g.foo devrait être abc, est : xyz
dans le second contexte de requête
g.foo devrait être abc, est : xyz
définition de g.foo à pqr
g.foo devrait être pqr, est : pqr
dans le contexte de l'application, après le second contexte de requête
g.foo devrait être abc, est : pqr
Comme l'a dit Y4Kman ci-dessus, "Chaque requête pousse un nouveau contexte d'application". Et comme le disent les docs de Flask, le contexte d'application "ne sera pas partagé entre les requêtes". Maintenant, ce qui n'a pas été explicitement dit (bien que je suppose que cela découle de ces déclarations), et ce que mes tests montrent clairement, c'est que vous ne devriez jamais créer explicitement plusieurs contextes de requête imbriqués dans un contexte d'application, car flask.g
(et compagnie) n'a pas de magie permettant de fonctionner dans les deux "niveaux" de contexte, avec des états différents existant indépendamment aux niveaux de l'application et de la requête.
La réalité est que le "contexte de l'application" est potentiellement un nom assez trompeur, car app.app_context()
est un contexte par requête, exactement le même que le "contexte de requête". Pensez-y comme un "contexte de requête allégé", uniquement nécessaire dans le cas où vous avez besoin de certaines des variables qui nécessitent normalement un contexte de requête, mais vous n'avez pas besoin d'accéder à un objet de requête (par exemple, lors de l'exécution d'opérations de base de données en lot dans un script shell). Si vous essayez d'étendre le contexte de l'application pour englober plus d'un contexte de requête, vous cherchez des ennuis. Donc, plutôt que mon test ci-dessus, vous devriez plutôt écrire du code comme ceci avec les contextes de Flask :
from flask import Flask, g
app = Flask(__name__)
with app.app_context():
print('dans le contexte de l'application, avant le premier contexte de requête')
print('définition de g.foo à abc')
g.foo = 'abc'
print('g.foo devrait être abc, est : {0}'.format(g.foo))
with app.test_request_context():
print('dans le premier contexte de requête')
print('g.foo devrait être None, est : {0}'.format(g.get('foo')))
print('définition de g.foo à xyz')
g.foo = 'xyz'
print('g.foo devrait être xyz, est : {0}'.format(g.foo))
with app.test_request_context():
print('dans le second contexte de requête')
print('g.foo devrait être None, est : {0}'.format(g.get('foo')))
print('définition de g.foo à pqr')
g.foo = 'pqr'
print('g.foo devrait être pqr, est : {0}'.format(g.foo))
Ce qui donnera les résultats attendus :
dans le contexte de l'application, avant le premier contexte de requête
définition de g.foo à abc
g.foo devrait être abc, est : abc
dans le premier contexte de requête
g.foo devrait être None, est : None
définition de g.foo à xyz
g.foo devrait être xyz, est : xyz
dans le second contexte de requête
g.foo devrait être None, est : None
définition de g.foo à pqr
g.foo devrait être pqr, est : pqr
0 votes
Je suis d'accord, c'est un changement assez étrange. Espérons que mitsuhiko implémente une sorte d'objet de contexte de requête pour remplacer
g
dans la version 0.10, sinon il semble que beaucoup de code pourraient commencer à développer des bugs sournois.13 votes
FWIW, Armin Ronacher (auteur de Flask) a sorti une suite de "Schémas avancés de Flask" qui montre du code d'exemple sur comment utiliser le nouveau
flask.g
. speakerdeck.com/mitsuhiko/advanced-flask-patterns-11 votes
Également une nouvelle demande de contexte implique un nouveau contexte d'application, donc cela devrait simplement fonctionner correctement en utilisation normale