web-dev-qa-db-fra.com

le signal post_save n'est pas appelé

J'ai déjà lu toutes les questions connexes.

J'ai deux Django, et les signaux fonctionnent bien dans un, mais ne fonctionnent pas dans le second (je viens de copier-coller du code et de changer les noms respectivement).

J'ai une application de commandes avec le modèle de commande. L'application est incluse dans le paramètre INSTALLED_APPS.

J'ai la configuration de l'application dans apps.py:

from Django.apps import AppConfig


class OrdersConfig(AppConfig):
    name = 'orders'

    def ready(self):
        super(OrdersConfig, self).ready()

        # noinspection PyUnresolvedReferences
        import signals

__init__.py:

default_app_config = 'orders.apps.OrdersConfig'

Et enfin, signaux.py:

@receiver(post_save, sender=Order)
def order_save(sender, instance, created, **kwargs):
    print 'Post save'
    if created:
        print 'Created'
        send_email_new_order.delay(settings.MODERATOR_EMAIL, instance.pk)

Et le signal n'est pas appelé. Pourquoi?

Django 1.10.3.

18
int_32

Quand post_save serait-il viré?

Ce que dit le document: à la fin de la méthode d'enregistrement.

Ce que cela signifie vraiment: à la fin de la réussite de la méthode de sauvegarde.

Quand le signal ne serait-il pas déclenché?

  1. Si la méthode save ne sauvegarde pas correctement l'objet (par exemple, lorsqu'un IntegrityError se produit)
  2. Lorsque vous appelez MyModel.objects.update()
  3. Lorsque vous remplacez la méthode save et oubliez d'appeler la méthode superclasse.
  4. Lorsque votre récepteur de signal n'a pas été enregistré avec succès.

Comment enregistrer le récepteur

Le plus simple est d'utiliser le @receiver décorateur comme vous l'avez fait. L'alternative est d'utiliser

from Django.db.models.signals import pre_save

pre_save.connect(order_save, sender='app_label.MyModel')

Où ce code doit-il être placé?

De nos jours, le manuel déclare que

À strictement parler, la gestion du signal et le code d'enregistrement peuvent vivre où vous le souhaitez, bien qu'il soit recommandé d'éviter le module racine de l'application et son module de modèles pour minimiser les effets secondaires de l'importation de code.

C'est probablement pourquoi dans ce cas, vous avez créé un fichier appelé signaux.py et placez votre code à l'intérieur de celui-ci et vous êtes allé à tous ces problèmes avec la classe AppConfig et la méthode ready. Mais assez curieusement, le manuel Django 1.6 dit:

Vous pouvez mettre le code de traitement et d'enregistrement du signal où vous le souhaitez. Cependant, vous devez vous assurer que le module dans lequel il se trouve est importé très tôt afin que la gestion des signaux soit enregistrée avant d'envoyer des signaux. Cela fait de models.py votre application un bon endroit pour enregistrer les gestionnaires de signaux.

Donc, si vous rencontrez des difficultés pour enregistrer votre récepteur de signal, vous pouvez réellement essayer de mettre votre code dans models.py ou views.py et laisser de côté les bits d'AppConfig (peut-être même supprimer complètement AppConfig)

Si vous souhaitez effectuer l'enregistrement dans AppConfig et que vous rencontrez des problèmes avec @reciever et/ou les importations, vous pouvez essayer

from Django.db.models.signals import pre_save
from app_label.signals import my_reciever

def ready(self):
    pre_save.connect(my_reciever, sender='app_label.MyModel')

Comment éviter les répétitions?

Le signal est-il déclenché deux fois? Assurez-vous d'enregistrer le récepteur une seule fois. Si vous l'enregistrez dans AppConfig, laissez-le hors de models.py et vice-verce

21
e4c5

Êtes-vous absolument sûr que le signals correct est importé? (print('hi, signals here') dans le module?)

Vous souhaiterez peut-être utiliser une importation absolument qualifiée (import orders.signals) ou un parent (import .signals as signals), aussi.

5
AKX

Avez-vous une autre application également appelée signals?

Essayez l'importation relative dans la méthode ready: from . import signals

4
jatinderjit