There are many Stack Overflow posts about recursion using the post_save
signal, to which the comments and answers are overwhelmingly: \"why not override save()\
Don't disconnect signals. If any new model of the same type is generated while the signal is disconnected the handler function won't be fired. Signals are global across Django and several requests can be running concurrently, making some fail while others run their post_save handler.
You should use queryset.update() instead of Model.save() but you need to take care of something else:
It's important to note that when you use it, if you want to use the new object you should get his object again, because it will not change the self object, for example:
>>> MyModel.objects.create(pk=1, text='')
>>> el = MyModel.objects.get(pk=1)
>>> queryset.filter(pk=1).update(text='Updated')
>>> print el.text
>>> ''
So, if you want to use the new object you should do again:
>>> MyModel.objects.create(pk=1, text='')
>>> el = MyModel.objects.get(pk=1)
>>> queryset.filter(pk=1).update(text='Updated')
>>> el = MyModel.objects.get(pk=1) # Do it again
>>> print el.text
>>> 'Updated'
the Model's .objects.update()
method bypasses the post_save signal
Try this something like this:
from django.db import models
from django.db.models.signals import post_save
class MyModel(models.Model):
name = models.CharField(max_length=200)
num_saves = models.PositiveSmallIntegerField(default=0)
@classmethod
def post_save(cls, sender, instance, created, *args, **kwargs):
MyModel.objects.filter(id=instance.id).update(save_counter=instance.save_counter + 1)
post_save.connect(MyModel.post_save, sender=MyModel)
In this example, an object has a name and each time .save()
is called, the .num_saves
property is incremented, but without recursion.