I have some problems when using signal
in Django.
post_save
occurs recursion because of instance.save()
inside of function.
If you want to avoid recursion in post_save
signal, just use Model.objects.filter(id=id).update(object=object)
Disconnect the signal before save, then connect again. https://docs.djangoproject.com/en/1.10/topics/signals/#disconnecting-signals
def post_save_product(sender, instance, **kwargs):
post_save.disconnect(post_save_product, sender=sender)
instance.do_stuff()
instance.save()
post_save.connect(post_save_product, sender=sender)
post_save.connect(post_save_product, sender= Product)
Just use pre_save
, you don't need to use .save()
method inside it again.
In the second case, you are comparing the database value of instance.color
to the display value. These will never match. You should check against the database value instead:
@receiver(post_save, sender=Variation)
def post_save_variation(sender, instance, created, **kwargs):
if not instance.price:
if instance.color == 'black':
instance.price = 40000
elif instance.color == 'single':
instance.price = 50000
elif instance.color == 'multi':
instance.price = 60000
instance.save()
Similarly you should set the default to the database value, i.e. default = 'black'
.
In your original code, all the checks will fail, and instance.price
is never updated to a non-empty value. The call to instance.save()
will trigger the post_save
signal again, not instance.price
is still true, and the instance is saved again without setting the price. This is the infinite recursion you're seeing.
In the first example, the slug
is always set to a non-empty value, so when the post_save
signal is triggered the second time, the if not instance.slug
check will fail, and the instance will not be saved a third time.
In both cases you're saving the instance at least twice if the slug/price is not set. To prevent this, you can use the pre_save
signal. You won't have to save the instance again in the signal handler:
@receiver(pre_save, sender=Variation)
def pre_save_variation(sender, instance, **kwargs):
if not instance.price:
if instance.color == 'black':
instance.price = 40000
elif instance.color == 'single':
instance.price = 50000
elif instance.color == 'multi':
instance.price = 60000