Django: disconnect a post_save signal to avoid recursion
Question:
This is my model:
class Paper(models.Model):
...
collection = models.ForeignKey(Collection, on_delete=models.CASCADE)
rang = models.IntegerField(default=0)
class Meta:
ordering = ['collection','rang']
When saving the model, I want it to update all the ‘rang’ fields in each object of the model so that they increase by 10.
I use the post_save signal below to avoid a problem of recursion:
@receiver(post_save, sender=Papier)
def redifine_rang(sender, *args, **kwargs):
for idx, paper in enumerate(Paper.objects.filter(collection = kwargs['instance'].collection)):
paper.rang = idx*10
Signal.disconnect(post_save, sender=Papier)
paper.save()
Signal.connect(post_save, sender=Papier)
However, I can’t get the signal to disconnect and connect. Does anyone have any recommendations?
Answers:
you can just use update
Paper.objects.filter(pk=paper.pk).update(rang=idx*10)
instead of
paper.rang = idx*10
Signal.disconnect(post_save, sender=Papier)
paper.save()
Signal.connect(post_save, sender=Papier)
A little clarification about the way to disable particular post_save
signal. This way:
Signal.disconnect(post_save, sender=Papier)
is didn’t work for Django 2.2.
The working option of turning off the signal will look like:
from django.db.models.signals import post_save
from django.dispatch import Signal
Signal.disconnect(post_save, receiver=redifine_range, sender=Papier)
It doesn’t work for Django 4.0.
Now you need to disable a certain handler for the signal.
post_save.disconnect(your_handler, sender=Papier)
This is my model:
class Paper(models.Model):
...
collection = models.ForeignKey(Collection, on_delete=models.CASCADE)
rang = models.IntegerField(default=0)
class Meta:
ordering = ['collection','rang']
When saving the model, I want it to update all the ‘rang’ fields in each object of the model so that they increase by 10.
I use the post_save signal below to avoid a problem of recursion:
@receiver(post_save, sender=Papier)
def redifine_rang(sender, *args, **kwargs):
for idx, paper in enumerate(Paper.objects.filter(collection = kwargs['instance'].collection)):
paper.rang = idx*10
Signal.disconnect(post_save, sender=Papier)
paper.save()
Signal.connect(post_save, sender=Papier)
However, I can’t get the signal to disconnect and connect. Does anyone have any recommendations?
you can just use update
Paper.objects.filter(pk=paper.pk).update(rang=idx*10)
instead of
paper.rang = idx*10
Signal.disconnect(post_save, sender=Papier)
paper.save()
Signal.connect(post_save, sender=Papier)
A little clarification about the way to disable particular post_save
signal. This way:
Signal.disconnect(post_save, sender=Papier)
is didn’t work for Django 2.2.
The working option of turning off the signal will look like:
from django.db.models.signals import post_save
from django.dispatch import Signal
Signal.disconnect(post_save, receiver=redifine_range, sender=Papier)
It doesn’t work for Django 4.0.
Now you need to disable a certain handler for the signal.
post_save.disconnect(your_handler, sender=Papier)