12
votes

Django Pre_Save Signal ne fonctionne pas

J'ai testé le signal "Pre_Save" de Django de la manière suivante, mais ne peut pas attraper le signal dans l'un ou l'autre d'entre eux.

$ xxx

  1. exécutez le code ci-dessus dans gequage.py shell: Ensuite, j'exécute mon site Web et voir Models.Save () Travaillez avec succès, mais la fonction de rappel ne fonctionne pas.

  2. Alternativement, j'exécute le code ci-dessus sur Shell, puis exécutez des modèles.Save () dans la coquille. "SAVE" fonctionne bien, mais rien n'arrive toujours à la fonction de rappel.

  3. Enfin, j'ai incorporé le code ci-dessus dans un __ init __. py fichier et toujours, exécutez la fonction Enregistrer () sur le site Web. Néanmoins, rien ne se passe.

    Souhaitez-vous s'il vous plaît m'aider à comprendre pourquoi le signal pré_save semble ne pas fonctionner?


1 commentaires

Avez-vous essayé d'ajouter le code dans votre fichier modèles.py ?


4 Réponses :


-1
votes

comme décrit dans le Django signaux doc the pre_save code> Signal Acceptez 3 arguments uniques (pas des arguments de mots clés) Donc, vous devez modifier votre my_callback code> fonction pour être aussi suivant:

def my_callback(sender,instance, using, **kwargs):
    logging.debug("======================================")


2 commentaires

En fait, ces arguments ne sont pas des arguments, mais des valeurs stockées à l'intérieur de la dicte Kwargs.


Eh bien, c'est en fait la même chose. Mais Django Docs Say dit que les récepteurs de signaux devraient accepter (expéditeur, ** kwargs), je suppose que la compatibilité future, plutôt que de nommer les arguments spécifiques du signal.



10
votes

Vous ne définissez pas la classe de l'expéditeur pour une. xxx pré>

Deuxièmement, si vous utilisez django 1.3, vous devez utiliser la nouvelle syntaxe de décorateur. P>

# Inside your models.py
from django.db import models
from django.db.models.signals import pre_save
from django.dispatch import receiver

class MyModel(models.Model):
    field1 = models.TextField()
    field2 = models.IntegerField()

@receiver(pre_save, sender=MyModel)
def mymodel_save_handler(sender, **kwargs):
    logging.debug("======================================")


3 commentaires

Vous n'êtes pas obligé de spécifier la classe de l'expéditeur, ni d'utiliser la syntaxe de décorateur. La raison pour laquelle il n'a pas fonctionné n'est rien de ce qui précède, c'est parce qu'il attache les signaux dans un fil différent à l'endroit où la sauvegarde se produit.


Notez que pour le code @Receiver pour fonctionner, vous devez également importer un récepteur de Django.Dispatch


Pour une raison quelconque, ce code n'a fonctionné que lorsque le récepteur du signal était dans le même modèle.py où l'émetteur de signal était (modèle).



3
votes

La raison de la réponse de la raison Eric a fait que cela fonctionne est parce qu'il vous a eu pour connecter le signal à l'intérieur de modèles.py, de sorte que lorsque vous enregistrez ensuite le modèle via votre site Web, le gestionnaire de signal est dans le même processus que le feu de signal.

Dans les exemples 1 et 3, il est facile de voir pourquoi ils n'ont pas fonctionné - vous économisez dans un processus différent (le site Web) à l'endroit où vos récepteurs de signaux écoutent.

J'aimerais mieux comprendre pourquoi l'exemple 2 est également cassé, mais je viens de déboguer un problème similaire dans mon propre projet tout en testant des signaux dans la coquille et que c'est certainement quelque chose à voir avec les expéditeurs de signaux et les récepteurs qui ne sont pas capables de «voir» chacun autre.


5 commentaires

Je ne sais pas si c'est la bonne explication, mais il est certainement intéressant et d'être critiqué ou voté. Mais je ne vois pas pourquoi ce serait un fil ou un processus différent ...


C'est un processus différent car on est la session de coquille manage.py, l'autre est le manage.py Runserver ... C'est la même codeBase mais ils fonctionnent indépendamment des modifications apportées aux objets de la coque (connexion du gestionnaire de signal). t Affecter les objets équivalents du serveur Web


(Assurez-vous que «processus» est le terme correct, plutôt que «fil» comme je l'utilisais dans le commentaire de la réponse d'Eric)


Oui, je pense que c'est raison pour 1, mais pas 3 Si c'est une application Django init .Py (ni 2). Aussi, ce logging.debug semble très suspect à moi => Voir ma réponse


d'accord sur 3, tant que le code a été rechargé sur le serveur Web