Reputation: 68426
I am using django 2.0.8 and Python 3.5. I want to be able to send and receive custom signals when an object is saved to the database.
I have followed the Django documentation on listening to signals and also the core signals bundled with Django - however, I am unable to get my example to work.
This is what I have so far:
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!
Can anyone explain why the signal is not being fired?
Upvotes: 8
Views: 5223
Reputation: 32214
You are reinventing the wheel, but only putting it on one side of the cart, so to speak.
the post_save signal is always sent on save, so defining your own signal is overkill. I know you got the argument there, but the receiver has the sender
argument already, which is the saved object, so you can just do sender.name
and you got the value you need.
Apart from that, you have a syntax error, your custom save function for your model is not indented. I don't know if this is a formatting error in your question or if that is how it looks in your code. Either way, should work if you just drop your custom signal.
Model
from django.db import models
import django.dispatch
class Foo(models.Model):
name = models.CharField(max_length=16)
Signals
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
Sample
from myapp.models import Foo
foo = Foo(name='Homer Simpson')
foo.save()
Upvotes: 1
Reputation: 778
It seems you need two features supplied by Django. signal and contenttypes.
So read the doc first
The model Activity is related to contenttypes,seems you miss object_id Field, which indicate which model instance is being crud.
For every crud action, An Activity instance is being created.This part is just the code written in signal.py
signal: signal have to connect each concrete model. Fortunately,See the source code of decorator receiver.
We have a signal list [post_save,post_delete] and a model list (FoodooChile, FooBarChile) to connect .
In post_save,argument created indicate the action is create or update.
At last, Usually we import the signal file in urls.py, maybe not the best practice.
It is also related to your settings.py
. use 'myapp.apps.MyappConfig'
replace myapp
in settings.py
,or define default_app_config = 'myapp.apps.MyappConfig'
in myapp/__init__.py
. The link above in comments describe this in detail
Upvotes: 8
Reputation: 166
myapp.signals
you have a receiver that handels the post_save signal (@receiver(post_save, sender=Foo)
) it doesn't connect to your signal.default_app_config = 'myapp.apps.MyappConfig'
To connect to the signal you created try this in your signals.py file:
@receiver(my_signal)
def my_handler(name, **kwargs):
print(name)
Upvotes: 1