form.save_m2m and intermediary models

938 views
Skip to first unread message

Delta20

unread,
Mar 19, 2009, 5:21:17 PM3/19/09
to Django users
I'm getting the error "Cannot set values on a ManyToManyField which
specifies an intermediary model." when I try to call form.save_m2m()
and I would appreciate any tips as to how to work around this.

Here's some code that illustrates what I am doing:

---
# Using a basic form in a view function:

ticket = form.save(commit=False)
ticket.save()
form.save_m2m() # this does not work

---
# in models.py:

class System(models.Model):
# fields omitted for brevity

class Ticket(models.Model):
systems = models.ManyToManyField(System, through='SystemTicket')

def do_stuff(self):
# Do some stuff that has to happen after m2m

# custom m2m so we can act on the post_save signal
class SystemTicket(models.Model):
ticket = models.ForeignKey(Ticket)
system = models.ForeignKey(System)

def update_stuff(instance, **kwargs):
instance.ticket.do_stuff()
instance.ticket.save()

post_save.connect(update_stuff, sender=SystemTicket)

Delta20

unread,
Mar 19, 2009, 5:25:09 PM3/19/09
to Django users
I forgot to add: the full error message is:

"Cannot set values on a ManyToManyField which specifies an
intermediary model. Use SystemTicket's Manager instead."

I'm not sure how I'd use the manager in this particular case though.

Malcolm Tredinnick

unread,
Mar 19, 2009, 6:50:06 PM3/19/09
to django...@googlegroups.com
On Thu, 2009-03-19 at 14:21 -0700, Delta20 wrote:
> I'm getting the error "Cannot set values on a ManyToManyField which
> specifies an intermediary model." when I try to call form.save_m2m()
> and I would appreciate any tips as to how to work around this.

The error is telling you exactly what the problem is. You can't do the
automatic assignment to many-to-many relations that use an intermediate
table. The reason being that the whole point of an intermediate table is
that it has *extra* information specified on it (otherwise you could
just use a normal ManyToManyField). So you need to create objects with
that extra information and save then explicitly.

Short version is you can't use save_m2m() in that case for precisely
this reason. You'll need to extract out the necessary data from the
form, and save it on the intermediate model.

Regards,
Malcolm

Delta20

unread,
Mar 19, 2009, 7:29:42 PM3/19/09
to Django users
On Mar 19, 6:50 pm, Malcolm Tredinnick <malc...@pointy-stick.com>
wrote:
> The error is telling you exactly what the problem is. You can't do the
> automatic assignment to many-to-many relations that use an intermediate
> table. The reason being that the whole point of an intermediate table is
> that it has *extra* information specified on it (otherwise you could
> just use a normal ManyToManyField). So you need to create objects with
> that extra information and save then explicitly.
>
> Short version is you can't use save_m2m() in that case for precisely
> this reason. You'll need to extract out the necessary data from the
> form, and save it on the intermediate model.

In this case, all I need is the post_save signal for when the m2m is
saved. The reason being is that I have Ticket.do_stuff in the example
above computes the value of a field in Ticket and the value depends on
what what Systems are related.

Is there a way I can achieve that without a custom intermediate model?
Manually invoking a method to do this doesn't work because that would
break in cases like modifying things in admin.



Reply all
Reply to author
Forward
0 new messages