web-dev-qa-db-fra.com

Où mettre le code de démarrage de Django?

J'aimerais que ces lignes de code soient exécutées au démarrage du serveur (développement et production):

from Django.core import management
management.call_command('syncdb', interactive=False)

Le mettre dans settings.py ne fonctionne pas, car cela nécessite que les paramètres soient déjà chargés.

Les placer dans une vue et accéder à cette vue à l'extérieur ne fonctionne pas non plus, car certains middlewares utilisent la base de données et ceux-ci échoueront et ne me laisseront pas accéder à la vue.

Les mettre dans un middleware fonctionnerait, mais cela serait appelé chaque fois que l'on accédait à mon application. Une solution possible pourrait être de créer un middleware qui effectue tout le travail, puis se supprime de MIDDLEWARE_CLASSES afin de ne plus l'appeler. Puis-je faire cela sans trop de singe-patcher?

50
Attila O.

Ecrivez un middleware qui le fait dans __init__ et ensuite, soulevez Django.core.exceptions.MiddlewareNotUsed à partir du __init__, Django le supprimera pour toutes les requêtes :). Au fait, __init__ est appelé au démarrage, pas à la première demande. Il ne bloquera donc pas votre premier utilisateur.

On parle d’ajouter un signal de démarrage, mais cela ne sera pas disponible bientôt (un problème majeur, par exemple, est le moment où ce signal doit être envoyé)

Ticket associé: https://code.djangoproject.com/ticket/13024

Mise à jour: Django 1.7 inclut le support pour cela. ( Documentation , liée au ticket)

55
KillianDS

Si vous utilisiez Apache/mod_wsgi pour les deux, utilisez le fichier de script WSGI décrit dans:

http://blog.dscpl.com.au/2010/03/improved-wsgi-script-for-use-with.html

Ajoutez ce dont vous avez besoin après l'activation des traductions.

Ainsi:

import sys

sys.path.insert(0, '/usr/local/Django/mysite')

import settings

import Django.core.management
Django.core.management.setup_environ(settings)
utility = Django.core.management.ManagementUtility()
command = utility.fetch_command('runserver')

command.validate()

import Django.conf
import Django.utils

Django.utils.translation.activate(Django.conf.settings.LANGUAGE_CODE)

# Your line here.
Django.core.management.call_command('syncdb', interactive=False)

import Django.core.handlers.wsgi

application = Django.core.handlers.wsgi.WSGIHandler()
4

Vous pouvez créer une commande personnalisée et écrire votre code dans la fonction handle. Détails ici https://docs.djangoproject.com/en/dev/howto/custom-management-commands/

Ensuite, vous pouvez créer un script de démarrage qui exécute le serveur Django, puis exécute votre nouvelle commande personnalisée.

3
Emam

Si vous utilisez mod_wsgi, vous pouvez le mettre dans l'application de démarrage wsgi

1
Aviah Laor

Dans Django 1.7+, si vous souhaitez exécuter un code de démarrage et,

1. Évitez de le lancer dans des migrations, des migrations, des sessions Shell,.

2. Évitez de courir deux fois ou plus

Une solution serait:

fichier: myapp/apps.py

from Django.apps import AppConfig

def startup():
    # startup code goes here

class MyAppConfig(AppConfig):
    name = 'myapp'
    verbose_name = "My Application"
    def ready(self):
        import os
        if os.environ.get('RUN_MAIN'):
            startup()

fichier: myapp/__init__.py

default_app_config = 'myapp.apps.MyAppConfig'

Ce message utilise les suggestions de @Pykler et @bdoering

0
Joseph Bani

Voici comment je contourne le signal de démarrage manquant pour Django: https://github.com/lsaffre/djangosite/blob/master/djangosite/models.py Le code appelé mon projet sur le djangosite est spécifique, mais le truc pour le faire appeler en écrivant une application spéciale (basée sur une idée de Ross McFarland) devrait fonctionner pour d'autres environnements . Luc

0
Luc Saffre