djangodjango-admindjango-ormdjango-signals

Issue with ManyToMany Relationships not updating immediately after save


I'm having issues with ManytoMany Relationships that are not updating in a model when I save it (via the admin) and try to use the new value within a function attached to the post_save signal or within the save_model of the associated AdminModel. I've tried to reload the object within those functions by using the get function with the id.. but it still has the old values.

Is this a transaction issue? Is there a signal thrown when the transaction ends?

Thanks,


Solution

  • When you save a model via admin forms it's not an atomic transaction. The main object gets saved first (to make sure it has a PK), then the M2M is cleared and the new values set to whatever came out of the form. So if you are in the save() of the main object you are in a window of opportunity where the M2M hasn't been updated yet. In fact, if you try to do something to the M2M, the change will get wiped out by the clear(). I ran into this about a year ago.

    The code has changed somewhat from the pre-ORM refactor days, but it boils down to code in django.db.models.fields.ManyRelatedObjectsDescriptor and ReverseManyRelatedObjectsDescriptor. Look at their __set__() methods and you'll see manager.clear(); manager.add(*value) That clear() complete cleans out any M2M references for the current main object in that table. The add() then sets the new values.

    So to answer your question: yes, this is a transaction issue.

    Is there a signal thrown when the transaction ends? Nothing official, but read on:

    There was a related thread a few months ago and MonkeyPatching was one method proposed. Grégoire posted a MonkeyPatch for this. I haven't tried it, but it looks like it should work.