Question

I'm having a hard time to grasp this post_save/pre_save signals from django.

What happens is that my model has a field called status and when a entry to this model is added/saved, it's status must be changed accordingly with some condition.

My model looks like this:

 class Ticket(models.Model):    
    (...)   
    status = models.CharField(max_length=1,choices=OFFERT_STATUS, default='O')

And my signal handler, configured for pre_save:

def ticket_handler(sender, **kwargs):
   ticket = kwargs['instance']
   (...)
   if someOtherCondition:
       ticket.status = 'C'

Now, what happens if I put aticket.save() just bellow this last line if statement is a huge iteration black hole, since this action calls the signal itself. And this problem happens in both pre_save and post_save.

Well... I guess that the capability of altering a entry before (or even after) saving it is pretty common in django's universe. So, what I'm doing wrong here? Is the Signals the wrong approach or I'm missing something else here?

Also, would it be possible to, once this pre_save/post_save function is triggered, to access another model's instance and change a specific row entry on that?

Thanks

Was it helpful?

Solution

Signals are not a proper approach for updating fields in the same model prior to save. Override the model's save method instead of using a signal for this case.

def save(self, force_insert=False, force_update=False):
    status = whatever....
    super(Ticket, self).save(force_insert, force_update)

For updates to other models, signals are a great approach because you can easily decouple your models. Specifically, you can add a pre_/post_save signal to trigger actions without the need to modify the code of the saved model (which could reside in another application from a third party).

OTHER TIPS

I agree with Carles that this may belong in a save(). When you must do this with signals, make sure you have a very tight condition around the save(). Your test could be rewrtitten as:

   if someOtherCondition and ticket.status != 'C':
       ticket.status = 'C'
       ticket.save()

You won't get into infinite recursion with the test done this way.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top