post_save signal NOT coming from model.save() as documented

I have a task that creates a new instance of a model and I want a signal to trigger something else.

The documentation on signals says the post_save signal is sent when a model.save() is executed, but in my testing it appears that only web POST as from a form trigger that signal.

The part of my celery task that successfully creates a record does not send a signal, either with objscts.create or modelsave()


 # Save prediction to database Predictions table
        p = Predictions(sepal_length=sepal_length,
                                    sepal_width=sepal_width,
                                    petal_length=petal_length,
                                    petal_width=petal_width,
                                    prediction=prediction_name)
        p.save()

        # Predictions.objects.create(sepal_length=sepal_length,
        #                             sepal_width=sepal_width,
        #                             petal_length=petal_length,
        #                             petal_width=petal_width,
        #                             prediction=prediction_name)

The signal is caught by

@receiver(post_save, sender=Predictions)
def post_save_pcreate(sender, instance, created, **kwargs):
    print()
    print('OOOOOOOOOOOOOOOOOOOOOOO Review.signals.Predictions.post_save signal')
    print()

and I see this OOO only when posting a new record in Predictions in the admin pages or the application web page, not with the task, although Prediction records are created in all three ways.

Is there a way around this?

You’re kinda half-right.

Signals are an “in-process” event, they’re not system global.

If that post_save function is being called, you would see the output in the console where celery is being run, not in your main Django console. To prove whether the signal is being called in Celery, you might want to use some other mechanism to create your audit trail, such as writing to a log file or an audit table - I’m not sure how Celery handles print output from its tasks.

Beyond that, you would expect to see that output from your main Django process in any situation in your main Django process where model.save is called, not just a form submission. But that call needs to be made in your Django process, not an external process.

<opinion> (Note: I’ve written multiple posts here in the forum about how dangerous an idea it is to build your application around using Django signals. In general, they don’t work in the way that most people assume they work, and the differences between those expectations and reality frequently cause problems.
There are specific situations where they’re necessary, but those are the only times when they should be used. In all other cases, I believe there are better and safer alternatives.) </opinion>

Ken,

Yes In my experiments I see signals working from shell executing a class method but not when that same class method is called from a task. Knowing that I can work around it.

Thanks
Mike

So I’m wondering, how are you verifying that it’s not being called by the task? The absence of the print output is not proof.

Ken, thanks, but I know because it creates a related model in the shell or rest api but not from a task. Yes not based on lack of print as the task is out of process.