Question

J'ai un code qui jette les causes syncdb jeter une erreur (car il tente d'accéder au modèle avant que les tables sont créées).

Y at-il un moyen de garder le code de courir sur syncdb? quelque chose comme:

if not syncdb:
    run_some_code()

Merci:)

modifier : PS - Je pensais à l'aide du signal de post_init ... pour le code qui accède au db, est qu'une bonne idée

Plus d'infos

Voici quelques informations supplémentaires comme demandé:)

Je l'ai rencontré ce une ou deux fois, par exemple ... Je Hacking django-Cron et déterminé qu'il fallait assurer qu'il n'y a pas d'emplois existants lorsque vous chargez django (car il recherche toutes les applications installées pour emplois et les ajoute à la charge de toute façon).

J'ajouté le code suivant au début du fichier __init__.py:

import sqlite3

try:
        # Delete all the old jobs from the database so they don't interfere with this instance of django
        oldJobs = models.Job.objects.all()
        for oldJob in oldJobs:
                oldJob.delete()
except sqlite3.OperationalError:
        # When you do syncdb for the first time, the table isn't 
        # there yet and throws a nasty error... until now
        pass

Pour des raisons évidentes, cela est de la merde. il est lié à sqlite et je suis, il y a de meilleurs endroits pour mettre ce code (ce qui est à quel point je suis tombé sur la question), mais cela fonctionne.

Comme vous pouvez voir l'erreur que vous obtenez est erreur opérationnelle (en sqlite) et la trace de la pile dit quelque chose le long des lignes de « tableau django_cron_job not found »

Solution

En fin de compte, l'objectif était de exécuter du code avant que les pages ont été chargées .

Ceci peut être accompli en exécutant dans le fichier urls.py, car il doit être importé avant une page peut être servi (évidemment).

Et j'ai pu enlever cette vilaine essayer / except :) Merci Dieu (et S. Lott)

Était-ce utile?

La solution

« modifier: PS - Je pensais à l'aide du signal de post_init ... pour le code qui accède au db, est-ce une bonne idée »

Jamais.

Si vous avez du code qui est l'accès au modèle avant que les tables sont créées, vous avez de gros, gros problèmes. Vous faites probablement quelque chose de grave.

Normalement, vous exécutez syncdb environ une fois. La base de données est créée. Et votre application Web utilise la base de données.

Parfois, vous avez fait un changement de conception, et recréez la base de données. Et puis votre application Web utilise cette base de données depuis longtemps.

(en général) ne pas besoin du code dans un module __init__.py. Vous devriez avoir (presque) jamais un code exécutable qui fonctionne réel dans un module __init__.py. Il est très, très rare et inappropriée pour Django.

Je ne sais pas pourquoi vous embêter avec __init__.py quand Django Cron dit que vous faites vos arrangements de planification dans urls.py.


Modifier

dossiers de compensation est une chose.

déconner avec __init__.py et de base.py de Django-Cron sont clairement des moyens tout à fait tort de le faire. S'il est si compliqué que ça, vous le faites mal.

Il est impossible de dire ce que vous essayez de faire, mais il devrait être trivial.

Votre urls.py ne peut courir après syncdb et après tout le matériel ORM a été configuré et lié correctement.

Votre urls.py pourrait, par exemple, supprimer certaines lignes, puis ajouter quelques lignes à une table. À ce stade, toutes les questions de syncdb sont hors du chemin.

Pourquoi avez-vous pas votre logique urls.py?

Autres conseils

Le code qui tente d'accéder aux modèles avant qu'ils ne soient créés peuvent très bien exister seulement au niveau du module; il devrait être un code exécutable Exécuter lorsque le module est importé, comme exemple indique. Ceci est, comme vous l'avez deviné, la raison par syncdb échoue. Il tente d'importer le module, mais le fait d'importer le module provoque le code de niveau d'application à exécuter; un « effet secondaire » si vous voulez.

Le désir d'éviter les importations de modules qui causent des effets secondaires est si forte en Python que la convention de if __name__ == '__main__': pour les scripts python exécutables est devenu monnaie courante. Lors du chargement juste une bibliothèque de code provoque une application pour commencer à exécuter, des maux de tête ensuivent: -)

Pour les applications Django, cela devient plus un mal de tête. Pensez à l'effet d'avoir exécuté oldJob.delete() chaque fois que le module est importé. Il peut sembler comme il est l'exécution d'une seule fois lorsque vous exécutez avec le serveur de développement de Django, mais dans un environnement de production, il sera exécuté se assez souvent. Si vous utilisez Apache, par exemple, Apache va souvent le feu en place plusieurs processus enfants en attente autour pour traiter les demandes. En tant que serveur de longue durée progresse, votre application Django se bootstrapped chaque fois qu'un gestionnaire est fourchue pour votre serveur web, ce qui signifie que le module sera importé et delete() sera appelé à plusieurs reprises, souvent de façon imprévisible. Un signal ne sera pas utile, malheureusement, que le signal pourrait être déclenché à chaque fois qu'un processus Apache est initialisé ainsi.

Il n'est pas, d'ailleurs, juste un serveur web qui pourrait causer votre code à exécuter par inadvertance. Si vous utilisez des outils comme epydoc, par exemple, ils importeront votre code pour générer la documentation de l'API. Cela provoquerait votre logique d'application pour commencer l'exécution, ce qui est évidemment un effet secondaire indésirable de l'exécution d'un analyseur juste de la documentation.

Pour cette raison, le code de nettoyage comme celui-ci est soit mieux gérée par une tâche cron, qui recherche des vieux emplois sur une base périodique et nettoie la DB. Ce script personnalisé peut également être exécuté manuellement ou par tout procédé (par exemple lors d'un déploiement, ou dans le cadre de votre fonction test setUp() unité pour assurer un essai propre). Peu importe la façon dont vous le faites, le point important est que le code comme celui-ci doit toujours être exécuté explicitement , plutôt que implicitement à la suite de l'ouverture du fichier source.

J'espère que cela aide. Je sais que cela ne fournit pas un moyen de déterminer si syncdb est en cours d'exécution, mais la question de syncdb disparaîtra comme par magie si vous concevez votre application Django avec le déploiement de la production à l'esprit.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top