Django formset data does not get saved when initial values are provided

django, forms, formset

Solution

I had a similar issue using django extra views.

I solved it bay modifying the form class that is passed to the inlineformset_factory. the ModelForm.has_changed method was returning false.

class TaskActionGroupForm(ModelForm):

    model = YourModel

    def has_changed(self):
        """
        Overriding this, as the initial data passed to the form does not get noticed, 
        and so does not get saved, unless it actually changes
        """
        changed_data = super(ModelForm, self).has_changed()
        return bool(self.initial or changed_data)

Problem

I have a formset which has some initial data provided - it's a data cloned from other model which contains 2 fields 'group' and 'requested'. When initial data is provided the forms in formset do not get saved, they only get saved when I'll modify the form with the data a little bit. When no initial data is provided forms do get saved. Why adding intial data to a formset makes it impossible to save formsets data to the database? This is my formset existing in get_context_data dictionary: ``` initial = ProcedureActionGroup.objects.filter(procedure__id=self.kwargs.get('pk', None)) initial_values = initial.values('group', 'requested') print initial_values initial_count = initial.count() ActionGroupFormset = inlineformset_factory(self.model, TaskGroup, extra=initial_count, form=TaskActionGroupForm, can_delete=False, ) data['formset'] = ActionGroupFormset(self.request.POST or None, initial=initial_values, **self.get_formset_kwargs()) ``` This is my form_valid method where I save all data ``` def form_valid(self, form): context = self.get_context_data() forms = [] forms.append(form.is_valid()) if self.get_procedure_obj(): formset = context['formset'] forms.append(formset.is_valid()) if all(forms): self.object = form.save(commit=False) form.save() if self.get_procedure_obj(): formset = formset.save(commit=False) for obj in formset: obj.task = self.object obj.save() self.object.extract_users() return HttpResponseRedirect(self.object.get_absolute_url()) ``` Model: ``` class TaskGroup(models.Model): task = models.ForeignKey(Task, null=True, blank=False) group = models.ForeignKey(ActionGroup, null=True, blank=True) requested = models.PositiveIntegerField(u'Requested', null=True, blank=True) ``` form template: ``` <form method="post" action="" class="span6 offset2 form form-horizontal"> {% crispy form%} {{formset.management_form}} {% if formset %} <div> <fieldset> <table class="table table-striped"> {% for form in formset%} <tr> {% for field in form %} <td> {{field}} </td> {% endfor %} </tr> {% endfor %} </table> </fieldset> </div> {% endif %} <div class="form-actions"> <button class="btn btn-primary btn-large" type="submit"> Save </button> </div> </form> ```

Original source