Opened 8 years ago
Closed 8 years ago
#28970 closed New feature (wontfix)
Option to suppress signals on save to avoid loop
| Reported by: | Gustavo Henrique de Almeida Gonçalves | Owned by: | nobody |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 2.0 |
| Severity: | Normal | Keywords: | signal suppress save recursion loop problem |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description (last modified by )
Calling instance.save() inside a post_save signal receiver causes a loop and max recursion error. This problem is very easy to fall into and the best solution at the moment is call the QuerySet update() method, so that the post_save signal is not called in this case.
This is a very ugly workaround. I think Django should give the option to call save() and explicitly suppress signal emitting. For example:
instance.save(post_save=False)
In the above method call, post_save signal would not be sent, and the loop problem would not occurs.
Change History (4)
comment:1 by , 8 years ago
| Description: | modified (diff) |
|---|
comment:2 by , 8 years ago
I can think about a case when working with asynchronous tasks, for example:
signals.py
from django.dispatch import receiver
from django.db.models.signals import post_save
from .models import ReferenceModel
from .tasks import async_task
@receiver(post_save, sender=ReferenceModel)
def process_image(sender, instance, created, **kwargs):
async_task.delay(instance.id)
tasks.py
from celery.decorators import task
from .models import ReferenceModel
@task
def async_task(object_id):
instance = ReferenceModel.objects.get(object_id)
# do some update
instance.save()
In this case you might not want the instance.save() inside the task to generate a post_save signal, otherwise the same task would be performed again.
comment:3 by , 8 years ago
In that case, I think async_task should set an attribute like instance._processed = True which the process_image() handler could check for.
comment:4 by , 8 years ago
| Resolution: | → wontfix |
|---|---|
| Status: | new → closed |
Feel free to raise the idea on the DevelopersMailingList if you disagree with the wontfix decision.
Resaving the object in
post_save()doesn't sound like a common use case (or a wise thing to do, from a performance standpoint). Can you explain your use case?