[Fixed]-Django Form's save_m2m() with save(commit=False) not working — Requesting model field to have a value

1👍

Update & Answer

The issue was due to me using BetterModelForm Django package. BetterModelForm divides forms into fieldsets to allow for repeatable or multiple forms on the same page. As a result the method of save_m2m() was not propagating through on the form but on a formset which required a different way to call save_m2m().

I fixed this by converting my BetterModelForm classes to standard forms.ModelForm and when the fieldsets were removed everything worked as expected.

NOTE** I also was providing a UserProfile queryset to my form and my model accepted a User object. I updated the code to provide the correct queryset to my form as well.

Updated code is as follows:

forms.py

class AgendaForm(forms.ModelForm):
    time_fmt = ["%I:%M %p"]
    date_fmt = ["%Y/%m/%d"]

    start = forms.SplitDateTimeField(label="Meeting Start", input_time_formats=time_fmt,
                                     input_date_formats=date_fmt,
                                     widget=forms.widgets.SplitDateTimeWidget(date_format=date_fmt[0], time_format=time_fmt[0]))
    end = forms.SplitDateTimeField(label="Meeting End", input_time_formats=time_fmt,
                                     input_date_formats=date_fmt,
                                     widget=forms.widgets.SplitDateTimeWidget(date_format=date_fmt[0], time_format=time_fmt[0]))

    location = forms.CharField(initial='TBD')

    class Meta:
        model = Agenda
        fields = ["start", "end", "location", "announcements", "agenda"]


class MinutesForm(forms.ModelForm):
    participants = UserModelMultipleChoiceField(queryset=User.objects.all(), widget=forms.CheckboxSelectMultiple())

    class Meta:
        model = Minutes
        fields = ["participants","minutes"]

views.py

class MinutesCreate(LoginRequiredMixin, View):
    @method_decorator(permission_required('pd.add_agenda'))
    def dispatch(self, *args, **kwargs):
        return super(MinutesCreate, self).dispatch(*args, **kwargs)

    def get(self, request, **kwargs):
        minutes_form = MinutesForm()
        return render(request, "pd/minutes_form.html", {"form": minutes_form, "kwargs": kwargs})

    def post(self, request, **kwargs):
        minutes_form = MinutesForm(request.POST)
        if minutes_form.is_valid():
            minutes = minutes_form.save(commit=False)
            minutes.author = request.user
            ag = get_object_or_404(Agenda, start__year=kwargs.get('year'),
                               start__month=kwargs.get('month'),
                               start__day=kwargs.get('day'))
            minutes.agenda = ag
            minutes.save()
            minutes_form.save_m2m()
            return redirect('pd:agenda_detail', **kwargs)
        return render(request, 'pd/minutes_form.html', {'form': minutes_form})

Leave a comment