﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
12337	save_m2m() does not honor save_instance's exclude argument	Margie Roginski	Stephen Burrows	"save_m2m() does not seem to honor the exclude argument that is passed in to save_instance.  I have a form that includes a particular m2m field, however I am trying to avoid saving that field.  To do this I am setting self._meta.exclude explicitly, just prior to calling the form's save method. After saving the task, I do the standard save_m2m() to save the m2m fields.  I find that non-m2m fields are correctly excluded from the save if specified in this way via self._meta.exclude, but that m2m fields are not excluded from the save if specified this way.  This seems inconsistent.

I suppose it could be rejected as a bug based on the fact that exclude is a model meta attribute, and if used exactly as specified in the doc, I wouldn't have the field in my form at all, so this wouldn't come up.

Here is some background on what I am doing to make a case for fixing this.  I have an app sort of like the admin app.  Say I have a model called 'foo'.  User A views it and user B views it.  User A then changes field 'status', and saves it.  User B then changes field 'priority' and saves it.  I need to avoid having user B's save change the 'status' field, since user B didn't modify that field.  I am using the hidden initial functionality to detect that user B has not changed the status field, and then I am setting self._meta.exclude to all fields in the form that were not changed by the user.  This all works fine the fields are non-m2m fields, but breaks down when an m2m field is placed in self._meta.exclude.

Currently save_m2m() is defined like this:

{{{
    def save_m2m():
        opts = instance._meta
        cleaned_data = form.cleaned_data
        for f in opts.many_to_many:
            if fields and f.name not in fields:
                continue
            if f.name in cleaned_data:
                f.save_form_data(instance, cleaned_data[f.name])
}}}

I find that if I define it like this instead, the m2m fields correctly are omitted from the save if they are in exclude.  This seems like more consistent and useful behavior to me.

{{{
    def save_m2m():
        opts = instance._meta
        cleaned_data = form.cleaned_data
        for f in opts.many_to_many:
            if fields and f.name not in fields:
                continue
            if exclude and f.name in exclude:   <=== added this if clause
                continue
            if f.name in cleaned_data:
                f.save_form_data(instance, cleaned_data[f.name]) 
}}}

"	Bug	closed	Forms	dev	Normal	fixed			Accepted	1	0	0	0	0	0
