Django Signals maximum recursion depth when updating model field

Viewed 33

I am trying to update a status field via signals but get a max recursion error. Using django 4.1.1.

models.py

class Product(models.Model):
  # ….
    PRODUCT_STATUS = (
        ('P', _('Preparation')),
        ('S', _('Sold')),
        ('T', _('Shipped')),
    )

    status = models.CharField(max_length=1, null=True,
                              choices=PRODUCT_STATUS, default='P')
    price_sold = models.DecimalField(
        _('Price Sold'), max_digits=10, decimal_places=2, blank=True, null=True)

#…

signals.py

@receiver(post_save, sender=Product)
def post_save_product_set_status_sold_if_price_sold(sender, instance, created, **kwargs):
    if instance.price_sold != None:
        instance.status = 'S'
        instance.save(update_fields=['status'])

I get the following error when saving

RecursionError at /admin/products/product/14/change/ maximum recursion depth exceeded while calling a Python object

Can somebody help?

1 Answers

it is clear. On after_save Product signal you call save Product and it triggered signal after_save Product and .... recursion.

in your case:

def post_save_product_set_status_sold_if_price_sold(sender, instance, *args, **kwargs):
    if instance.price_sold != None:
        type(instance).objects.filter(pk=instance.pk).update(status = 'S')

And probably you need pre-save signal. https://docs.djangoproject.com/en/4.1/ref/signals/#pre-save

But i don't understand, why you want to do it with signal. You can:

  • check it on form.clean() (best)
  • check it on model.full_clean() (good)
  • do it on form.save() (normal)
  • do it on model.save() (weak)
Related