I've already read all related questions.
I have two Django projects, and signals work fine in one, but do not work in second one (I've just copy-pasted code and changed names respectively).
I have an orders app with Order model. App is included in INSTALLED_APPS setting.
I have app config in 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'
And, finally, signals.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)
And signal does not getting called. Why?
Django 1.10.3.
There are two ways to send signals in Django. To send a signal, call either Signal. send() (all built-in signals use this) or Signal. send_robust() .
In the example above, save_profile is our receiver function, User is the sender and post_save is the signal. You can read it as: Everytime when a User instance finalize the execution of its save method, the save_profile function will be executed. If you supress the sender argument like this: post_save.
pre_save. This is sent at the beginning of a model's save() method. Arguments sent with this signal: sender.
Django Signals - post_delete()To notify another part of the application after the delete event of an object happens, you can use the post_delete signal.
A lot of others have suggested that if your post_save is having to update data on a field that is should be done in the save method on the model and not in a post_save signal.. What do you think? It think disconnecting signals can cause concurrency problems.
Any time you want to use a function or perform an action after a certain model has been saved, you can use a post_save signal. So now that you know what a post_save signal is and when to use it, let's go over an actual example in Django code. This will be quick.
I tend to use the post_save signal fairly often as a good way to get around overriding the default save method on models. Recently though I ran into an issue where I was hitting the “maximum recursion depth exceeded” error when I was saving the current model from within the post_save signal. If you think about it, that makes a lot of sense.
What the document says: At the end of the save method.
What it really means: At the end of the successful completion of the save method.
save
method does not successfully save the object (such as when an IntegrityError
occurs)MyModel.objects.update()
save
method and forget to call the superclass method.Simplest is to use the @receiver
decorator as you have done. The alternative is to use
from django.db.models.signals import pre_save pre_save.connect(order_save, sender='app_label.MyModel')
Nowadays, the manual states that
Strictly speaking, signal handling and registration code can live anywhere you like, although it’s recommended to avoid the application’s root module and its models module to minimize side-effects of importing code.
That is probably why in this instance you have created a file called signals.py and place your code inside that and gone to all that trouble with the AppConfig class and the ready method. But funnily enough, the Django 1.6 manual says:
You can put signal handling and registration code anywhere you like. However, you’ll need to make sure that the module it’s in gets imported early on so that the signal handling gets registered before any signals need to be sent. This makes your app’s models.py a good place to put registration of signal handlers.
So if you are having trouble getting your signal receiver registered you can actually try putting your code in models.py
or views.py
and leave out the bits from AppConfig (maybe even remove AppConfig completely)
If you want to carry out the registration in AppConfig, and you are having trouble with @reciever
and/or imports, you can try
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')
Does the signal get fired twice? Make sure that you register the receiver only once. If you register it in AppConfig
, leave it out of models.py
and vice verce
Are you aaaaaabsolutely sure the correct signals
is imported? (print('hi, signals here')
in the module?)
You might want to use an absolutely qualified import (import orders.signals
) or a relative one (import .signals as signals
), too.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With