Exécuter du code lors de Django commence une FOIS seulement?
Je suis en train d'écrire un Django Middleware de la classe que je veux exécuter qu'une seule fois au démarrage, à l'initialisation de certains autres arbritary code. J'ai suivi la très belle solution posté par sdolan ici, mais le message "Hello" est sortie sur le terminal deux fois. E. g.
from django.core.exceptions import MiddlewareNotUsed
from django.conf import settings
class StartupMiddleware(object):
def __init__(self):
print "Hello world"
raise MiddlewareNotUsed('Startup complete')
et dans mon Django fichier de paramètres, j'ai la classe inclus dans le MIDDLEWARE_CLASSES
liste.
Mais lorsque je l'exécute à l'aide de Django runserver et demande une page, j'obtiens dans le terminal
Django version 1.3, using settings 'config.server'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Hello world
[22/Jul/2011 15:54:36] "GET /HTTP/1.1" 200 698
Hello world
[22/Jul/2011 15:54:36] "GET /static/css/base.css HTTP/1.1" 200 0
Des idées pourquoi "Hello world" est imprimé deux fois? Merci.
- juste par curiosité, avez-vous compris pourquoi le code dans init.py est exécuté deux fois?
- il sera exécuté deux fois sous runserver ... c'est parce que runserver première charges jusqu'à la apps pour les inspecter et puis en fait, le serveur démarre. Même sur autoreload de runserver le code est seulement une fois exec.
- Wow, j'ai été ici.... alors, merci encore pour le commentaire de @Pykler, c'est ce que je me demandais.
Vous devez vous connecter pour publier un commentaire.
Mise à jour de Pykler la réponse ci-dessous: Django 1.7 a maintenant un crochet pour ce
Ne pas faire de cette façon.
Vous ne voulez pas "middleware" pour un temps de démarrage chose.
Vous souhaitez exécuter du code dans le haut-niveau
urls.py
. Ce module est importé et exécuté une seule fois.urls.py
my_app/models.py
?Mise à jour: Django 1.7 a maintenant un crochet pour ce
fichier:
myapp/apps.py
fichier:
myapp/__init__.py
Pour Django < 1.7
La réponse ne semble pas fonctionner, urls.py est chargé, dès la première demande.
Ce qui a bien fonctionné ces derniers temps, est de mettre le code de démarrage dans l'un de vos INSTALLED_APPS init.py par exemple
myapp/__init__.py
Lors de l'utilisation de
./manage.py runserver
... c'est exécutée deux fois, mais c'est parce que runserver a quelques trucs à valider les modèles premier, etc ... normal déploiements ou même quand runserver auto rechargements, ce n'est exécuté qu'une fois.myapp
il int wsgi.py est ce que j'ai fait, mais il ne fonctionne pas toujours! il échoue si vous êtes de départ des choses comme des sous-processus avec des tuyaux (ouais mortel droit) qui ne peut pas être partagé avec d'autres processus (depuis uwsgi fourches le processus d'origine dans un multi-modèle de travailleur.django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
sur Django 1.10 lorsque vous essayez cela, est-ce la réponse de date aujourd'hui?logging.config.dictConfig()
a été appelé. Enfin je l'ai mis avant cet appel.runserver
deux fois, et à tous les autres aspects de la gestion de la commande ainsi. Si bien, ne pas aller trop. Je pense que l'une des meilleures options est d'écrire un middleware, ou (ab)utilisation urls.pyfoo
, avecsettings.py
dansfoo/foo/settings.py
et diverses applications dansfoo/apps/app_a/...
,foo/apps/app_b/...
, etc.runfirst()
agit sur toutes les applications dansINSTALLED_APPS
. Exactement où dois-je placer monrunfirst()
code?Cette question est bien répondu dans le post de blog Point d'entrée crochet pour Django projets, qui va travailler pour Django >= 1.4.
Fondamentalement, vous pouvez utiliser
<project>/wsgi.py
pour le faire, et elle sera exécutée qu'une seule fois, lorsque le serveur démarre, mais pas lorsque vous exécutez des commandes ou de l'importation d'un module particulier.Si ça aide quelqu'un, en plus de pykler de l' réponse, "--noreload" option empêche runserver de l'exécution de commande au démarrage deux fois:
Mais la commande ne sera pas recharger runserver après les autres, par le code des changements.
os.environ.get('RUN_MAIN')
uniquement à l'exécution de votre code une fois dans le processus principal (voir la section stackoverflow.com/a/28504072)ready(self)
appels tout en étant capable de les lancer qu'une seule fois. Cheers!Comme suggéré par @Pykler, dans Django 1.7+ vous devez utiliser le crochet a expliqué dans sa réponse, mais si vous voulez que votre fonction n'est appelée que lorsque le serveur est appelé (et non pas lors de la prise de migrations, de migrer, shell, etc. sont appelés), et que vous voulez éviter AppRegistryNotReady exceptions que vous avez à faire comme suit:
fichier:
myapp/apps.py
Notez que vous ne peut pas fiabilité de la connexion à la base de données ou d'interagir avec des modèles à l'intérieur de la
AppConfig.ready
fonction (voir le avertissement dans les docs).Si vous avez besoin d'interagir avec la base de données dans votre start-up code, une possibilité est d'utiliser le
connection_created
signal pour exécuter du code d'initialisation lors de la connexion à la base de données.Évidemment, cette solution est pour l'exécution de code une fois par connexion de base de données, pas une fois par le début d'un projet. Vous devez donc raisonnable de la valeur pour l'
CONN_MAX_AGE
réglage de sorte que vous ne sont pas de ré-exécuter le code d'initialisation à chaque requête. Notez également que le serveur de développement ignoreCONN_MAX_AGE
, si vous exécutez le code une fois par requête en développement.99% du temps, c'est une mauvaise idée - initialisation de la base de code devrait aller dans les migrations - mais il y a quelques cas d'utilisation où vous ne pouvez pas éviter la fin de l'initialisation et les mises en garde ci-dessus sont acceptables.
my_receiver
fonction de déconnexion de laconnection_created
signal, plus précisément, ajouter le texte suivant à lamy_receiver
fonction:connection_created.disconnect(my_receiver)
.si vous voulez print "hello world" une fois de temps lorsque vous exécutez le serveur, mettre print ("bonjour le monde") hors de la classe StartupMiddleware