web-dev-qa-db-fra.com

Envoi et réception de signaux dans les modèles Django

J'utilise Django 2.0.8 et Python 3.5. Je veux pouvoir envoyer et recevoir des signaux personnalisés lorsqu'un objet est enregistré dans la base de données.

J'ai suivi la documentation de Django sur l'écoute de signaux ainsi que sur les signaux noyaux fournis avec Django -, mais je ne parviens pas à faire fonctionner mon exemple.

C'est ce que j'ai jusqu'ici:

myapp/models.py

from Django.db import models
import Django.dispatch

my_signal = Django.dispatch.Signal(providing_args=["name"])

class Foo(models.Model):
    name = models.CharField(max_length=16)

def save(self, *args, **kwargs):
    try:
        # Call the "real" save() method.
        super().save(*args, **kwargs)  

        # Fire off signal         
        my_signal.send(sender=self.__class__, name=self.name)

    except Exception as e:
        print ('Exception:', e)
        #pass

myapp/signaux.py

from Django.db.models.signals import post_save
from Django.dispatch import receiver
from .models import Foo


@receiver(post_save, sender=Foo)
def foo_handler(sender, **kwargs):
    print('Foo Signal Recieved!')
    print(kwargs)

myapp/app.py

class MyappConfig(AppConfig):
name = 'myapp'
label = 'myapp'

def ready(self):
    import myapp.signals

Utilisation de l'échantillon

from myapp.models import Foo

foo = Foo(name='Homer Simpson')
foo.save() # Object is saved, but event is not fired!

Quelqu'un peut-il expliquer pourquoi le signal n'est pas déclenché?

8

Il semble que vous ayez besoin de deux fonctionnalités fournies par Django. signal et types de contenu

Alors lisez d'abord le doc

Le modèle Activity est lié à contenttypes, vous semblez manquer le champ object_id, qui indique quelle instance de modèle est en cours de traitement.

Pour chaque action crud, une instance Activity est en cours de création. Cette partie correspond simplement au code écrit dans signal.py.

signal: le signal doit connecter chaque modèle concret. Heureusement, voir le code source de decorator receiver

Nous avons une liste de signaux [post_save, post_delete] et une liste de modèles (FoodooChile, FooBarChile) à connecter.

Dans post_save, l'argument created indique que l'action est créée ou mise à jour.

Enfin, nous importons généralement le fichier de signal dans urls.py, ce n’est peut-être pas la meilleure pratique.


Il est également lié à votre settings.py. utiliser 'myapp.apps.MyappConfig' remplacer myapp dans settings.py, ou définir default_app_config = 'myapp.apps.MyappConfig' dans myapp/__init__.py. Le lien ci-dessus dans les commentaires décrit cela en détail

6
newlife
  1. Dans le myapp.signals, vous avez un récepteur qui gère le signal post_save signal (@receiver(post_save, sender=Foo)) qui ne se connecte pas à votre signal.
  2. Assurez-vous que vous utilisez la configuration de votre application dans le répertoire __init__.py de votre application default_app_config = 'myapp.apps.MyappConfig'
  3. Pour vous connecter au signal que vous avez créé, essayez ceci dans votre fichier signaux.py:

    @receiver(my_signal)
        def my_handler(name, **kwargs):
            print(name)
    
0
Ghariani Mohamed

Vous réinventez la roue, mais vous ne la placez que d'un côté du chariot, pour ainsi dire.

le signal post_save est toujours envoyé lors de la sauvegarde; définir votre propre signal est donc excessif. Je sais que vous avez l'argument, mais le destinataire a déjà l'argument sender, qui est l'objet enregistré. Vous pouvez donc simplement faire sender.name et obtenir la valeur dont vous avez besoin.

En dehors de cela, vous avez une erreur de syntaxe, votre fonction de sauvegarde personnalisée pour votre modèle n'est pas mise en retrait. Je ne sais pas s'il s'agit d'une erreur de formatage dans votre question ou s'il en est ainsi dans votre code. De toute façon, devrait fonctionner si vous déposez simplement votre signal personnalisé.

Modèle

from Django.db import models
import Django.dispatch


class Foo(models.Model):
    name = models.CharField(max_length=16)

Des signaux

from Django.db.models.signals import post_save
from Django.dispatch import receiver
from .models import Foo


@receiver(post_save, sender=Foo)
def foo_handler(sender, **kwargs):
    print(sender.name)

App

class MyappConfig(AppConfig):
name = 'myapp'
label = 'myapp'

def ready(self):
    import myapp.signals

Échantillon

from myapp.models import Foo

foo = Foo(name='Homer Simpson')
foo.save()
0
firelynx