2011-10-15 4 views
5

J'ai des gestionnaires de signaux qui fonctionnent sur l'utilisateur Django. De plus j'utilise South. Ces gestionnaires de signaux dépendent de certaines migrations qui doivent être exécutées auparavant.Vérifiez par programme si syncdb est en cours d'exécution

Lorsque Django a exécuté snycdb et créé l'utilisateur admin, ces migrations ne se sont pas exécutées et les gestionnaires de signaux ont levé une exception.

Je cherche un moyen de détecter si Django exécute actuellement syncdb afin que les handerls de signal puissent passer l'exécution.

+1

South a son modèle et une table où il enregistre les informations sur lesquelles les migrations ont été exécutées et celles qui ne l'ont pas été. Peut-être pourriez-vous l'utiliser pour vérifier si les migrations dont vous avez besoin ont été exécutées? – Ski

+0

Ce serait également une option. Mais puisque les gestionnaires sont pour les signaux post-sauvegarde sur des modèles relativement souvent sauvés, je voudrais éviter un tour supplémentaire à la DB à ce stade. –

+1

Je pense que vous pouvez stocker ces informations en toute sécurité dans la variable globale et ne les récupérer qu'une seule fois lorsque l'application est démarrée. – Ski

Répondre

0

Je ne pense pas qu'il y ait un moyen de savoir si syncdb est en cours d'exécution, mais il y a une façon de gérer les exceptions en python:

juste attraper et exception et pass:

try: 
    # code that deals with django user 
except ExceptionYouAreGetting: 
    # seems like syncdb is running, let's pass for now 
    pass 
+1

Bien que ce soit une option, je ne veux pas avaler un 'DatabaseError' dans le gestionnaire car cela pourrait aussi indiquer d'autres problèmes sérieux. –

0

AFAIK il n'est pas possible de détecter si syncdb est en cours d'exécution, cependant, lorsque syncdb ou loaddata est en cours d'exécution, vos signaux recevront un argument supplémentaire raw.

@receiver(post_save, sender=ModelA) 
def signal_handler(sender, **kwargs): 
    raw = kwargs.get('raw', False) 
    if not raw: 
     <do whatever> 

De cette façon, vous pouvez passer des signaux à exécuter lorsque syncdb est en cours d'exécution.

+1

L'argument raw est uniquement True si les données sont en cours de chargement à partir d'un appareil. Cependant, certaines choses (comme l'utilisateur initial et le site par défaut) que django crée pendant le processus syncdb initial ne sont pas chargées à partir des fixtures, donc raw sera False comme dans tout autre scénario de sauvegarde. –

2

Je piège l'exception DatabaseError et vérifie si l'entrée ContentType pour le modèle que j'essaie d'utiliser existe, sinon je suppose que syncdb est en cours, sinon annule la transaction et relance l'exception d'origine. Cette méthode n'entraîne un accès DB supplémentaire que lorsque DatabaseError est déclenché.

with transaction.commit_on_success(): 
     try: 
      content_type = ContentType.objects.get_for_model(kwargs['instance']) 
      for relation in WorkflowTypeRelation.objects.filter(content_type=content_type): 
       workflow_instance = WorkflowInstance.objects.create(content_object=kwargs['instance'], 
        workflow_type=relation.workflow_type) 
     except DatabaseError as database_error: 
      try: 
       ContentType.objects.get(model='workflowtyperelation') 
      except ContentType.DoesNotExist: 
       # Most probable running during syncdb phase, 
       # so ignore the exception 
       pass 
      except DatabaseError: 
       # ContentType model DB table doesn't exists, 
       # raise original exception 
       raise database_error 
      else: 
       # The ContentType model exists, 
       # there is something wrong with the DB 
       # raise original exception 
       transaction.rollback() 
       raise database_error 
Questions connexes