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.