Question regarding post_save signal and ManyToMany field objects

987 views
Skip to first unread message

Ryan K

unread,
Jul 13, 2009, 2:27:12 PM7/13/09
to Django users
Recently I've been trying to get answers about the post_save signal
behavior and perhaps have been asking too much of readers without
narrowing down the problem enough myself. So here is my effort to ask
a rather straightforward question:

The code that connects to the post_save signal, according to the
signal docs, is passed three objects and I am only concerned about
one: the instance that was saved. Now this instance has a
ManyToManyField and what I am finding out according to be debugging is
that the instance's ManyToMany field is NOT being updated after save
is called.

So, for example, when the signal calls the handler (this is being done
via the admin interface but it shouldn't matter) and I check
instance.manytomanyfield, it does not show the most recent changes.
What is the best way to "force" the update of the table so I can get
accurate data from the ManyToMany field? Even if I explicitly do
something like this:

def __init__(self, sender, instance):
self.sender = sender
self.instance = sender.objects.select_related().get
(id=instance.id)

What seems like cached data is being when I test:

self.instance.manytomanyfield.all()

Can anyone help with this behavior?

Cheers,
Ryan

Eugene Mirotin

unread,
Jul 14, 2009, 4:08:44 AM7/14/09
to Django users
If I understand right, the problem is that you want the signal after
all related fields are already saved. If so, this is exactly the
problem I have too.
You see, when you have such a relation (and, for example, edit the
parent object with inlined related objects from the admin page, Django
_has to_ save the parent object first, and only then it saves the
related objects (you can verify it by adding print statements to your
save methods or handlers and running the dev server from terminal).
The reason is that when you initially create the object, related
objects have to link to the existing object, so the parent object is
saved before them.

Ryan K

unread,
Jul 14, 2009, 6:27:09 AM7/14/09
to Django users
Yea...it would be so elegant too! Here is a "bug" filing:
http://code.djangoproject.com/ticket/5390. It's been open for two
years....

I understand that your really getting what you asked for, just the
instance of the model you just saved but to me (and it seems you and a
lot of other people), intuition leads people to write code that drives
them nuts because its not really "post_transaction."

Russell Keith-Magee

unread,
Jul 14, 2009, 10:35:15 AM7/14/09
to django...@googlegroups.com
On Tue, Jul 14, 2009 at 6:27 PM, Ryan K<ryank...@gmail.com> wrote:
>
> Yea...it would be so elegant too! Here is a "bug" filing:
> http://code.djangoproject.com/ticket/5390. It's been open for two
> years....

A little history may help explain why this has been open for so long.

Historically (i.e., when dinosaurs roamed the Django source code)
signals were _very_ expensive - even signals that had no listeners. As
a result, there was a lot of resistance to adding new signals. Given
the performance cost, the decision was made to live without m2m
signals.

Just prior to v1.0, the signal framework was updated, which made
signals much faster. However, in an attempt to actually hit the
deadline for getting 1.0 out the door, adding new signals wasn't on
the plan.

Adding new signals was discussed as a possible feature for v1.1 (see
the features page [1]); however, nobody took charge of getting it
done, and other development priorities took over. The feature deadline
arrived before anyone got around to implementing (and integrating) the
change.

When the v1.2 development cycle starts, I'm sure this will be back on
the schedule again.

[1] http://code.djangoproject.com/wiki/Version1.1Features

Yours,
Russ Magee %-)

Alex Gaynor

unread,
Jul 14, 2009, 10:43:25 AM7/14/09
to django...@googlegroups.com
The best way now to get this feature is to use an intermediary model which obviously get's its own signals.  Additionally I've been working on refactoring m2ms to always use an intermediary model, thus signals would always be sent.

Alex

--
"I disapprove of what you say, but I will defend to the death your right to say it." -- Voltaire
"The people's good is the highest law." -- Cicero
"Code can always be simpler than you think, but never as simple as you want" -- Me

Ryan K

unread,
Jul 14, 2009, 4:35:54 PM7/14/09
to Django users
Alex,

So I have my Menus that contain links and a Link can be in multiple
Menus. Are you saying make an explicit model like:

class MenuLinks(models.Model):
menu = models.ForeignKey(Menu)
link = models. ForeignKey(Link)

?

Basically what I am doing is making an enhanced flatpages app called
staticpages. I want my client to have full control over the page's
content, menus associated with a page as well as links in the menu..
Here is my signals.py:

http://pastebin.com/m3c333dd

If I modify it to use the above table and connect to its post_save
signal, is my solution worth it? I use signals to generate an XHTML
menu and cache it in my database. I do this in a thread. Someone said
don't use threads. What is the consensus on that?

Cheers,
Ryan

On Jul 14, 10:43 am, Alex Gaynor <alex.gay...@gmail.com> wrote:
> On Tue, Jul 14, 2009 at 9:35 AM, Russell Keith-Magee <freakboy3...@gmail.com
>
>
>
>
>
> > wrote:
Reply all
Reply to author
Forward
0 new messages