1660230900
L'objectif de cet article est de clarifier le fonctionnement des contextes d'application et de demande dans Flask.
À la fin de cet article, vous devriez être en mesure d'expliquer :
current_app
, test_request_context
et test_client
avec les contextes correctsVous devriez également être en mesure de corriger l'erreur suivante :
RuntimeError: Working outside of application context.
This typically means that you attempted to use functionality that needed
to interface with the current application object in some way. To solve
this, set up an application context with app.app_context().
Contrairement à Django et à d'autres frameworks Web, les fonctions de vue Flask n'acceptent pas un objet de requête contenant des métadonnées sur la requête HTTP.
Django Exemple :
def users(request):
if request.method == 'POST':
# Save the form data to the database
# Send response
else:
# Get all users from the database
# Send response
Avec Flask, vous importez dans l'objet de requête comme ceci :
from flask import request
@app.route('/users', methods=['GET', 'POST'])
def users():
if request.method == 'POST':
# Save the form data to the database
# Send response
else:
# Get all users from the database
# Send response
Dans l'exemple Flask, l'objet de requête ressemble, se sent et agit comme une variable globale, mais ce n'est pas le cas.
Si l'objet de requête était une variable globale, vous ne pourriez pas exécuter une application Flask multithread car les variables globales ne sont pas thread-safe.
Au lieu de cela, Flask utilise des contextes pour faire en sorte qu'un certain nombre d'objets "agissent" comme des globals uniquement pour le contexte particulier (un thread, un processus ou une coroutine) utilisé. Dans Flask, cela s'appelle un context-local .
Les paramètres locaux de contexte sont similaires mais finalement différents de l' implémentation locale des threads de Python pour stocker des données spécifiques à un thread. L'implémentation de Flask est plus générique afin de permettre aux travailleurs d'être des threads, des processus ou des coroutines.
Lorsqu'une requête est reçue, Flask fournit deux contextes :
Le contexte | La description | Objets disponibles |
---|---|---|
Application | Assure le suivi des données au niveau de l'application (variables de configuration, enregistreur, connexion à la base de données) | current_app ,g |
Demande | Assure le suivi des données au niveau de la demande (URL, méthode HTTP, en-têtes, données de demande, informations de session) | request ,session |
Il convient de noter que chacun des objets ci-dessus est souvent appelé "proxies". Cela signifie simplement qu'ils sont des mandataires des saveurs globales des objets. Pour en savoir plus, consultez le deuxième article de cette série.
Flask gère la création de ces contextes lorsqu'une requête est reçue. Ils peuvent prêter à confusion car vous n'avez pas toujours accès à un objet particulier en fonction de l'état dans lequel se trouve votre application.
Regardons quelques exemples.
Supposons que vous ayez l'application Flask suivante :
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Welcome!'
if __name__ == '__main__':
app.run()
Voyons d'abord comment utiliser l' objet current_app pour accéder au contexte Application.
Dans le shell Python, si vous essayez d'accéder à l' current_app.config
objet en dehors d'une fonction d'affichage, vous devriez voir l'erreur suivante :
$ python
>>> from flask import current_app
>>> current_app.config
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "werkzeug/local.py", line 347, in __getattr__
return getattr(self._get_current_object(), name)
File "werkzeug/local.py", line 306, in _get_current_object
return self.__local()
File "flask/globals.py", line 52, in _find_app
raise RuntimeError(_app_ctx_err_msg)
RuntimeError: Working outside of application context.
This typically means that you attempted to use functionality that needed
to interface with the current application object in some way. To solve
this, set up an application context with app.app_context(). See the
documentation for more information.
Pour accéder aux objets exposés par les contextes Application et Requête en dehors d'une fonction d'affichage, vous devez d'abord créer le contexte approprié :
# without a context manager
$ python
>>> from app import app
>>> from flask import current_app
>>>
>>> app_ctx = app.app_context()
>>> app_ctx.push()
>>>
>>> current_app.config["ENV"]
'production'
>>> app_ctx.pop()
>>>
# with a context manager
$ python
>>> from app import app
>>> from flask import current_app
>>>
>>> with app.app_context():
... current_app.config["ENV"]
...
'production'
>>>
Vous pouvez utiliser la méthode test_request_context pour créer un contexte de requête :
# without a context manager
$ python
>>> from app import app
>>> from flask import request
>>>
>>> request_ctx = app.test_request_context()
>>> request_ctx.push()
>>>
>>> request.method
'GET'
>>>
>>> request.path
'/'
>>>
>>> request_ctx.pop()
>>>
# with a context manager
$ python
>>> from app import app
>>> from flask import request
>>>
>>> with app.test_request_context('/'):
... request.method
... request.path
...
'GET'
'/'
>>>
test_request_context
est généralement utilisé pendant les tests lorsque vous souhaitez utiliser des données de requête sans la surcharge d'une requête complète.
Le moment le plus courant pour rencontrer des problèmes avec le contexte de l'application et de la demande est lorsque votre application est en cours de test :
import pytest
from flask import current_app
from app import app
@pytest.fixture
def client():
with app.test_client() as client:
assert current_app.config["ENV"] == "production" # Error!
yield client
def test_index_page(client):
response = client.get('/')
assert response.status_code == 200
assert b'Welcome!' in response.data
Une fois exécutés, les tests échoueront dans le projecteur :
$ pytest
________________________ ERROR at setup of test_index_page _____________________
@pytest.fixture
def client():
with app.test_client() as client:
> assert current_app.config["ENV"] == "production"
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
def _find_app():
top = _app_ctx_stack.top
if top is None:
> raise RuntimeError(_app_ctx_err_msg)
E RuntimeError: Working outside of application context.
E
E This typically means that you attempted to use functionality that needed
E to interface with the current application object in some way. To solve
E this, set up an application context with app.app_context(). See the
E documentation for more information.
================================= 1 error in 0.13s =================================
Pour corriger, créez un contexte d'application avant d'accéder current_app
:
import pytest
from flask import current_app
from app import app
@pytest.fixture
def client():
with app.test_client() as client:
with app.app_context(): # New!!
assert current_app.config["ENV"] == "production"
yield client
def test_index_page(client):
response = client.get('/')
assert response.status_code == 200
assert b'Welcome!' in response.data
Pour résumer, utilisez les objets suivants dans les fonctions d'affichage, les commandes CLI et les fonctions de test :
Objet | Le contexte | Erreur commune | La solution |
---|---|---|---|
current_app | Contexte d'application | Travailler en dehors du contexte de l'application | with app.app_context(): |
g | Contexte d'application | Travailler en dehors du contexte de l'application | with app.test_request_context('/'): |
request | Contexte de la demande | Travailler en dehors du contexte de la demande | with app.test_request_context('/'): |
session | Contexte de la demande | Travailler en dehors du contexte de la demande | with app.test_request_context('/'): |
Les méthodes suivantes doivent être utilisées lors des tests :
Méthode du flacon | La description |
---|---|
test_client | Client de test pour l'application Flask |
test_request_context | Pousser le contexte de la demande pour les tests |
Source : https://testdrive.io
1660048200
Cet article explore le fonctionnement des contextes Application et Request dans Flask.
À la fin de cet article, vous devriez être en mesure d'expliquer :
current_app
et dans les fonctions d'affichagerequest
Pour exécuter le code que vous écrivez, il a besoin de données à traiter. Ces données peuvent être des données de configuration, des données d'entrée, des données de la base de données, etc.
Les contextes sont utilisés pour garder une trace des données dont votre code a besoin pour s'exécuter.
Dans Flask, les contextes sont utilisés pour fournir les données nécessaires au traitement des requêtes et des commandes de l'interface de ligne de commande (CLI).
Bien que cet article se concentre sur le traitement des requêtes, les concepts présentés s'appliquent également aux commandes CLI.
Commençons par la façon dont une demande est traitée à partir d'un haut niveau :
Ainsi, une requête est envoyée du navigateur au serveur Web (comme Nginx ou Apache) pour demander une URL spécifique ('/' URL dans le schéma ci-dessus). Le serveur Web achemine ensuite cette demande vers un serveur WSGI pour traitement.
WSGI, qui signifie Web Server Gateway Interface, est une interface entre un serveur Web et une application Web basée sur Python. C'est nécessaire car un serveur Web ne peut pas communiquer directement avec une application Python. Pour en savoir plus, consultez WSGI .
Le serveur WSGI demande à l'application Flask de traiter la demande.
L'application Flask génère une réponse, qui est renvoyée au serveur WSGI, puis au serveur Web et, finalement, au navigateur Web.
Ces étapes décrivent le cycle demande-réponse, qui est une fonction clé du traitement d'une demande via un serveur Web, un serveur d'application WSGI et une application Web.
Lorsqu'une requête est reçue, Flask fournit deux contextes :
Le contexte | La description | Objets disponibles |
---|---|---|
Application | Assure le suivi des données au niveau de l'application (variables de configuration, enregistreur, connexion à la base de données) | current_app ,g |
Demande | Assure le suivi des données au niveau de la demande (URL, méthode HTTP, en-têtes, données de demande, informations de session) | request ,session |
Il convient de noter que chacun des objets ci-dessus est souvent appelé "proxies". Cela signifie simplement qu'ils sont des mandataires des saveurs globales des objets. Nous approfondirons cela sous peu.
Flask gère la création de ces contextes lorsqu'une requête est reçue. Ils peuvent prêter à confusion car vous n'avez pas toujours accès à un objet particulier en fonction de l'état dans lequel se trouve votre application.
Le schéma suivant illustre le traitement des contextes lors du traitement d'une requête :
Il se passe beaucoup de choses dans ce diagramme, nous allons donc parcourir chaque étape en détail.
Tout commence lorsqu'une requête est reçue par le serveur Web :
Le travail du serveur Web consiste à acheminer les requêtes HTTP entrantes vers un serveur WSGI .
Apache et Nginx sont deux serveurs Web courants tandis que Gunicorn , uWSGI et mod_wsgi sont des serveurs WSGI populaires.
Il convient de noter que même si Flask Development Server est un serveur WSGI, il n'est pas destiné à être utilisé en production.
Afin de traiter la requête, le serveur WSGI génère un worker pour gérer la requête :
Le travailleur peut être un thread, un processus ou une coroutine. Par exemple, les travailleurs seraient des threads si vous utilisez Flask Development Server avec sa configuration par défaut.
Si vous souhaitez en savoir plus sur les différences entre les threads, le multitraitement et l'asynchronisme dans Python, consultez l' article Accélérer Python avec la concurrence, le parallélisme et l'asynchronie et la vidéo Concurrence dans Python .
Pour cette explication, le type de travailleur n'est pas important ; le point clé à propos du travailleur est qu'il traite une demande à la fois (d'où la nécessité de plus d'un travailleur).
Une fois l'exécution basculée vers l'application Flask, Flask crée les contextes Application et Request et les pousse sur leurs piles respectives :
Pour passer en revue, le contexte d'application stocke les données au niveau de l'application, telles que les variables de configuration, la connexion à la base de données et l'enregistreur. Le contexte Request, quant à lui, stocke les données spécifiques à la requête qui doivent être traitées afin de générer une réponse.
Cela peut être surprenant à voir, mais les deux piles sont implémentées en tant qu'objets globaux (cela deviendra plus clair dans la section suivante).
Maintenant que l'application Flask est prête à traiter les données (dans la fonction d'affichage) et que les données sont prêtes dans les piles de contexte d'application et de demande, nous avons besoin d'un moyen de connecter ces deux éléments... des proxys à la rescousse !
Les proxys sont utilisés par les fonctions de vue pour accéder aux contextes Application (stockés dans la pile de contexte Application) et Request (stockés dans la pile de contexte Request) :
current_app
- proxy vers le contexte d'application pour le travailleurrequest
- proxy vers le contexte de la requête pour le travailleurÀ première vue, cette séquence peut sembler déroutante, car la fonction de vue semble accéder aux objets globaux (piles de contexte d'application et de demande) via les proxys. Si tel était le cas, cette opération serait problématique, car elle n'est pas thread-safe. Vous pouvez également penser que ces piles (en tant qu'objets globaux) pourraient être accessibles par n'importe quel travailleur, ce qui serait un problème de sécurité.
Cependant, cette conception est l'une des grandes fonctionnalités de Flask... les piles sont implémentées en tant qu'objets contextuels .
Pour en savoir plus sur les proxys, consultez les notes sur les proxys de la documentation Flask et l' article sur le modèle de proxy .
Python a un concept de données locales de thread pour stocker des données spécifiques à un thread, qui sont à la fois "thread-safe et thread-unique". En d'autres termes, chaque thread pourra accéder aux données de manière sécurisée et les données sont toujours uniques au thread spécifique.
Flask implémente un comportement similaire (context-locals), mais de manière plus générique pour permettre aux travailleurs d'être des threads, des processus ou des coroutines.
Les contextes locaux sont en fait implémentés dans Werkzeug , qui est l'un des packages clés qui comprend Flask. Pour plus de simplicité, nous ferons référence à Flask lors de l'examen des contextes locaux.
Lorsque les données sont stockées dans un objet local au contexte, les données sont stockées de manière à ce qu'un seul travailleur puisse les récupérer. Par conséquent, si deux travailleurs distincts accèdent à un objet contextuel local, ils récupèrent chacun leurs propres données spécifiques qui sont uniques à chaque travailleur.
Un exemple utilisant un objet local contextuel sera présenté dans la section suivante.
Pour résumer, les proxies current_app
et request
sont disponibles dans chaque fonction de vue et ils sont utilisés pour accéder aux contextes à partir de leurs piles respectives, qui sont stockées en tant qu'objets locaux au contexte.
L'utilisation de 'pile' dans le contexte des piles de contexte Application et Demande rend ce concept encore plus déroutant qu'il ne l'est déjà. Ces "piles" ne stockent généralement pas plus d'un seul contexte.
La structure de données utilisée est une pile car il existe des scénarios très avancés (par exemple, des redirections internes ) qui nécessitent plus d'un élément.
Si vous deviez créer votre propre framework Web à partir de zéro, vous pourriez envisager de transmettre les contextes d'application et de demande dans chaque fonction d'affichage comme ceci :
@app.route('/add_item', methods=['GET', 'POST'])
def add_item(application_context, request_context): # contexts passed in!
if request_context.method == 'POST':
# Save the form data to the database
...
application_context.logger.info(f"Added new item ({ request_context.form['item_name'] })!")
...
En fait, un certain nombre de frameworks Web fonctionnent de la sorte (y compris Django ).
Cependant, Flask fournit les proxies current_app
et request
qui finissent par ressembler à des variables globales pour une fonction de vue :
from flask import current_app, request
@app.route('/add_item', methods=['GET', 'POST'])
def add_item():
if request.method == 'POST':
# Save the form data to the database
...
current_app.logger.info(f"Added new item ({ request.form['item_name'] })!")
...
En utilisant cette approche, la fonction de vue n'a pas besoin des contextes passés en tant qu'arguments ; cette approche permet une définition simplifiée de la fonction de vue. Cela peut prêter à confusion car vous n'avez pas toujours accès aux proxys current_app
et request
, selon l'état dans lequel se trouve votre application.
RAPPEL : Les proxies
current_app
etrequest
ne sont pas réellement des variables globales ; ils pointent vers des objets globaux qui sont implémentés en tant que contextes locaux, de sorte que les proxys sont toujours uniques à chaque travailleur.
Une fois la réponse générée, les contextes Request et Application sont extraits de leurs piles respectives :
Cette étape nettoie les piles.
La réponse est ensuite renvoyée au navigateur web, qui complète le traitement de cette requête.
Les objets contextuels locaux sont implémentés à l'aide d'objets locaux , qui peuvent être créés comme suit :
$ python
>>> from werkzeug.local import Local
>>> data = Local()
>>> data.user = 'pkennedy@hey.com'
Chaque contexte (c'est-à-dire, les 'travailleurs' discutés dans la section précédente) peut accéder à un Local
objet pour le stockage de données unique au contexte. Les données consultées sont propres au contexte et ne sont accessibles que par ce contexte.
Les objets LocalStack sont similaires aux Local
objets, mais conservent une pile d'objets à autoriser push()
et d' pop()
opérations.
Dans la section précédente, nous avons appris comment la pile de contexte d'application et la pile de contexte de demande sont utilisées lorsqu'une demande est traitée dans Flask. Ces piles sont implémentées en tant LocalStack
qu'objets dans la mémoire globale de Flask.
Pour aider à solidifier le fonctionnement des contextes locaux, parcourons un exemple en créant un LocalStack
objet dans la mémoire globale, puis en y accédant par trois threads distincts :
Voici le script complet pour cet exemple :
"""
Example script to illustrate how a global `LocalStack` object can be used
when working with multiple threads.
"""
import random
import threading
import time
from werkzeug.local import LocalStack
# Create a global LocalStack object for storing data about each thread
thread_data_stack = LocalStack()
def long_running_function(thread_index: int):
"""Simulates a long-running function by using time.sleep()."""
thread_data_stack.push({'index': thread_index, 'thread_id': threading.get_native_id()})
print(f'Starting thread #{thread_index}... {thread_data_stack}')
time.sleep(random.randrange(1, 11))
print(f'LocalStack contains: {thread_data_stack.top}')
print(f'Finished thread #{thread_index}!')
thread_data_stack.pop()
if __name__ == "__main__":
threads = []
# Create and start 3 threads that each run long_running_function()
for index in range(3):
thread = threading.Thread(target=long_running_function, args=(index,))
threads.append(thread)
thread.start()
# Wait until each thread terminates before the script exits by
# 'join'ing each thread
for thread in threads:
thread.join()
print('Done!')
Ce fichier crée un LocalStack
objet ( thread_data_stack
) pour stocker les données de chacun des threads qui seront créés.
thread_data_stack
imite la pile de contexte d'application ou la pile de contexte de demande dans Flask.
Le long_running_function
est exécuté dans chacun des threads :
def long_running_function(thread_index: int):
"""Simulates a long-running function by using time.sleep()."""
thread_data_stack.push({'index': thread_index, 'thread_id': threading.get_native_id()})
print(f'Starting thread #{thread_index}... {thread_data_stack}')
time.sleep(random.randrange(1, 11))
print(f'LocalStack contains: {thread_data_stack.top}')
print(f'Finished thread #{thread_index}!')
thread_data_stack.pop()
Cette fonction envoie des données sur le thread à l' thread_data_stack
objet dans la mémoire globale :
thread_data_stack.push({'index': thread_index, 'thread_id': threading.get_native_id()})
Cette opération imite le contexte d'application ou de demande poussé vers leur pile respective.
Une fois la time.sleep()
fonction terminée, les données du thread_data_stack
sont accessibles :
print(f'LocalStack contains: {thread_data_stack.top}')
Cette opération imite l'utilisation des proxys
app_context
etrequest
, car ces proxys accèdent aux données au sommet de leur pile respective.
A la fin de la fonction, les données sont extraites du thread_data_stack
:
thread_data_stack.pop()
Cette opération imite l'extraction du contexte Application ou Request de leur pile respective.
Lorsque le script est exécuté, il démarre 3 threads :
# Create and start 3 threads that each run long_running_function()
for index in range(3):
thread = threading.Thread(target=long_running_function, args=(index,))
threads.append(thread)
thread.start()
Et join
chaque thread pour que le script attende que chaque thread termine son exécution :
# Wait until each thread terminates before the script exits by
# 'join'ing each thread
for thread in threads:
thread.join()
Exécutons ce script pour voir ce qui se passe :
$ python app.py
Starting thread #0... <werkzeug.local.LocalStack object at 0x109cebc40>
Starting thread #1... <werkzeug.local.LocalStack object at 0x109cebc40>
Starting thread #2... <werkzeug.local.LocalStack object at 0x109cebc40>
LocalStack contains: {'index': 0, 'thread_id': 320270}
Finished thread #0!
LocalStack contains: {'index': 1, 'thread_id': 320271}
Finished thread #1!
LocalStack contains: {'index': 2, 'thread_id': 320272}
Finished thread #2!
Done!
Ce qui est vraiment intéressant à propos de chaque thread, c'est qu'ils pointent tous vers le même LocalStack
objet en mémoire :
Starting thread #0... <werkzeug.local.LocalStack object at 0x109cebc40>
Starting thread #1... <werkzeug.local.LocalStack object at 0x109cebc40>
Starting thread #2... <werkzeug.local.LocalStack object at 0x109cebc40>
Lorsque chaque thread accède à thread_data_stack
, l'accès est unique à ce thread ! C'est la magie de LocalStack
(et Local
) - ils permettent un accès contextuel unique :
LocalStack contains: {'index': 0, 'thread_id': 320270}
LocalStack contains: {'index': 1, 'thread_id': 320271}
LocalStack contains: {'index': 2, 'thread_id': 320272}
L'accès à
thread_data_stack
est également thread-safe, contrairement à l'accès à la mémoire globale typique.
L'un des aspects puissants (mais déroutants) de Flask est la manière dont les contextes Application et Request sont gérés. Espérons que cet article ait apporté des éclaircissements sur ce sujet !
Les contextes Application et Request fournissent les données nécessaires lors du traitement des requêtes ou des commandes CLI. Assurez-vous d'utiliser les proxys current_app
et request
pour accéder au contexte d'application et au contexte de demande.
Source : https://testdrive.io
1660230900
L'objectif de cet article est de clarifier le fonctionnement des contextes d'application et de demande dans Flask.
À la fin de cet article, vous devriez être en mesure d'expliquer :
current_app
, test_request_context
et test_client
avec les contextes correctsVous devriez également être en mesure de corriger l'erreur suivante :
RuntimeError: Working outside of application context.
This typically means that you attempted to use functionality that needed
to interface with the current application object in some way. To solve
this, set up an application context with app.app_context().
Contrairement à Django et à d'autres frameworks Web, les fonctions de vue Flask n'acceptent pas un objet de requête contenant des métadonnées sur la requête HTTP.
Django Exemple :
def users(request):
if request.method == 'POST':
# Save the form data to the database
# Send response
else:
# Get all users from the database
# Send response
Avec Flask, vous importez dans l'objet de requête comme ceci :
from flask import request
@app.route('/users', methods=['GET', 'POST'])
def users():
if request.method == 'POST':
# Save the form data to the database
# Send response
else:
# Get all users from the database
# Send response
Dans l'exemple Flask, l'objet de requête ressemble, se sent et agit comme une variable globale, mais ce n'est pas le cas.
Si l'objet de requête était une variable globale, vous ne pourriez pas exécuter une application Flask multithread car les variables globales ne sont pas thread-safe.
Au lieu de cela, Flask utilise des contextes pour faire en sorte qu'un certain nombre d'objets "agissent" comme des globals uniquement pour le contexte particulier (un thread, un processus ou une coroutine) utilisé. Dans Flask, cela s'appelle un context-local .
Les paramètres locaux de contexte sont similaires mais finalement différents de l' implémentation locale des threads de Python pour stocker des données spécifiques à un thread. L'implémentation de Flask est plus générique afin de permettre aux travailleurs d'être des threads, des processus ou des coroutines.
Lorsqu'une requête est reçue, Flask fournit deux contextes :
Le contexte | La description | Objets disponibles |
---|---|---|
Application | Assure le suivi des données au niveau de l'application (variables de configuration, enregistreur, connexion à la base de données) | current_app ,g |
Demande | Assure le suivi des données au niveau de la demande (URL, méthode HTTP, en-têtes, données de demande, informations de session) | request ,session |
Il convient de noter que chacun des objets ci-dessus est souvent appelé "proxies". Cela signifie simplement qu'ils sont des mandataires des saveurs globales des objets. Pour en savoir plus, consultez le deuxième article de cette série.
Flask gère la création de ces contextes lorsqu'une requête est reçue. Ils peuvent prêter à confusion car vous n'avez pas toujours accès à un objet particulier en fonction de l'état dans lequel se trouve votre application.
Regardons quelques exemples.
Supposons que vous ayez l'application Flask suivante :
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return 'Welcome!'
if __name__ == '__main__':
app.run()
Voyons d'abord comment utiliser l' objet current_app pour accéder au contexte Application.
Dans le shell Python, si vous essayez d'accéder à l' current_app.config
objet en dehors d'une fonction d'affichage, vous devriez voir l'erreur suivante :
$ python
>>> from flask import current_app
>>> current_app.config
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "werkzeug/local.py", line 347, in __getattr__
return getattr(self._get_current_object(), name)
File "werkzeug/local.py", line 306, in _get_current_object
return self.__local()
File "flask/globals.py", line 52, in _find_app
raise RuntimeError(_app_ctx_err_msg)
RuntimeError: Working outside of application context.
This typically means that you attempted to use functionality that needed
to interface with the current application object in some way. To solve
this, set up an application context with app.app_context(). See the
documentation for more information.
Pour accéder aux objets exposés par les contextes Application et Requête en dehors d'une fonction d'affichage, vous devez d'abord créer le contexte approprié :
# without a context manager
$ python
>>> from app import app
>>> from flask import current_app
>>>
>>> app_ctx = app.app_context()
>>> app_ctx.push()
>>>
>>> current_app.config["ENV"]
'production'
>>> app_ctx.pop()
>>>
# with a context manager
$ python
>>> from app import app
>>> from flask import current_app
>>>
>>> with app.app_context():
... current_app.config["ENV"]
...
'production'
>>>
Vous pouvez utiliser la méthode test_request_context pour créer un contexte de requête :
# without a context manager
$ python
>>> from app import app
>>> from flask import request
>>>
>>> request_ctx = app.test_request_context()
>>> request_ctx.push()
>>>
>>> request.method
'GET'
>>>
>>> request.path
'/'
>>>
>>> request_ctx.pop()
>>>
# with a context manager
$ python
>>> from app import app
>>> from flask import request
>>>
>>> with app.test_request_context('/'):
... request.method
... request.path
...
'GET'
'/'
>>>
test_request_context
est généralement utilisé pendant les tests lorsque vous souhaitez utiliser des données de requête sans la surcharge d'une requête complète.
Le moment le plus courant pour rencontrer des problèmes avec le contexte de l'application et de la demande est lorsque votre application est en cours de test :
import pytest
from flask import current_app
from app import app
@pytest.fixture
def client():
with app.test_client() as client:
assert current_app.config["ENV"] == "production" # Error!
yield client
def test_index_page(client):
response = client.get('/')
assert response.status_code == 200
assert b'Welcome!' in response.data
Une fois exécutés, les tests échoueront dans le projecteur :
$ pytest
________________________ ERROR at setup of test_index_page _____________________
@pytest.fixture
def client():
with app.test_client() as client:
> assert current_app.config["ENV"] == "production"
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
def _find_app():
top = _app_ctx_stack.top
if top is None:
> raise RuntimeError(_app_ctx_err_msg)
E RuntimeError: Working outside of application context.
E
E This typically means that you attempted to use functionality that needed
E to interface with the current application object in some way. To solve
E this, set up an application context with app.app_context(). See the
E documentation for more information.
================================= 1 error in 0.13s =================================
Pour corriger, créez un contexte d'application avant d'accéder current_app
:
import pytest
from flask import current_app
from app import app
@pytest.fixture
def client():
with app.test_client() as client:
with app.app_context(): # New!!
assert current_app.config["ENV"] == "production"
yield client
def test_index_page(client):
response = client.get('/')
assert response.status_code == 200
assert b'Welcome!' in response.data
Pour résumer, utilisez les objets suivants dans les fonctions d'affichage, les commandes CLI et les fonctions de test :
Objet | Le contexte | Erreur commune | La solution |
---|---|---|---|
current_app | Contexte d'application | Travailler en dehors du contexte de l'application | with app.app_context(): |
g | Contexte d'application | Travailler en dehors du contexte de l'application | with app.test_request_context('/'): |
request | Contexte de la demande | Travailler en dehors du contexte de la demande | with app.test_request_context('/'): |
session | Contexte de la demande | Travailler en dehors du contexte de la demande | with app.test_request_context('/'): |
Les méthodes suivantes doivent être utilisées lors des tests :
Méthode du flacon | La description |
---|---|
test_client | Client de test pour l'application Flask |
test_request_context | Pousser le contexte de la demande pour les tests |
Source : https://testdrive.io
1621684737
Looking for a top on-demand app development company in USA for your app development project?
AppClues Infotech is one of the most trusted and exceptional on-demand app development company in USA that has the greatest expertise in developing mobile apps in different industries. We have a dedicated on-demand app designer and programmer team that will help to create a perfect, user-friendly and secure mobile app for your business needs.
Why Choose Us for On-Demand Mobile App Development?
• Dedicated on-demand app developers
• A to Z on-demand app solutions
• Free Consultation
• High Experience in developing an on-demand app
• Expertise across different domains
• Flexible hiring models
• Quality Assurance
• Total technical support
For more info:
Website: https://www.appcluesinfotech.com/
Email: info@appcluesinfotech.com
Call: +1-978-309-9910
#on-demand app development company #hire on-demand mobile app developers #top on-demand app developers in usa #on-demand app development solution #on-demand app development solution #top on-demand app development company in usa
1615970455
Looking to hire an On-Demand mobile app Development Company in USA for your specific app development need? We at AppClues Infotech one of the leading app development company in USA that provides a wide range of On-Demand app development solutions that match your business requirements.
For more info:
Website: https://www.appcluesinfotech.com/
Email: info@appcluesinfotech.com
Call: +1-978-309-9910
#on-demand app development #hire on-demand mobile app development company in usa #hire on-demand app developers in usa #top on-demand app development company #best on-demand app development services #on-demand app development cost
1613383625
Looking for on-demand app development solutions for your business? At AppClues Infotech, we provide a wide range of on-demand services using the most advanced technology and proficiency of our team of expert on-demand app developers.
Send us your project requirement to get the exact cost of developing an on-demand app.
For more info:
Website: https://www.appcluesinfotech.com/
Email: info@appcluesinfotech.com
Call: +1-978-309-9910
#on-demand app development services #hire on-demand mobile app developers #on-demand mobile app solution #on-demand app development company in usa #top on-demand app development service #best on-demand app development agency