Search code examples
djangomany-to-manysignals

Can I detect ManyToManyField mutations before they are applied?


I have a Django app that broadcasts changes of some of its models to its clients, to keep them up-to-date. I have a separate app for that, that binds to the post_save signal of these models and triggers the broadcast.

Problems have come with models with ManyToManyFields. I am not very familiar with Django's handling of this but I understand that these fields are actually updated after the model is saved.

I was able to use the m2m_changed signal to react to the post_* actions and dispatch the broadcast after the object is all up-to-date. However, in the post_save handler, I still need to detect that the m2m field is going to be mutated, to avoid broadcasting incomplete data. How can I detect this , either in the post_save signal handler or the model's save method ? Is there a way to raise a flag on an object when a m2m field is about to be mutated ?

Here's what I've tried :

  • Handle the pre_* actions of the m2m_changed signal to detect incoming mutation of the field but that does not work, because the signal gets fired after post_save, which is too late (data has already been broadcasted).
  • Store initial values when the model instance is created, and compare them in the overriden save method to look for changes. This does not work because the fields are not changed and report to be == the initial value ; plus I read on other questions that this practice could cause race conditions.

Thanks a lot for the help.


Solution

  • I finally sorted this out. For reference:

    TL;DR: The model layer is not the right place to do this ; the view layer is.

    I re-implemented the notification system at the view level instead of doing it in the model layer. I made a mixin that adds notification features to my views. Thanks to this solution :

    • I got rid of signals
    • I got much better control over what’s going on, which simplified the notification handler code quite a bit.