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:
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
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)
class MyappConfig(AppConfig):
name = 'myapp'
label = 'myapp'
def ready(self):
import myapp.signals
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é?
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
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.default_app_config = 'myapp.apps.MyappConfig'
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)
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()